MySQL left join subquery fail - mysql

Following query runs well in MySQL 5.x
SELECT
m_area.id, m_area.cn_areaName, m_area.de_areaName,
m_area.en_areaName,m_area.jp_areaName,t_shop.count
FROM
m_area left join
(
select t_shop.areaID, count(areaID) AS count
from t_shop
group by t_shop.areaID
) t_shop
on m_area.id = t_shop.areaID
However, when I have to run it in a 4.0.23 MySQL DB with same DB structure and data it just return following message:
1064 - You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '[
select t_shop.areaID, count(areaID) AS count
from t_s
I tried many times but still failed. Is left join to subquery not allowed in MySQL 4.x ? Then that mean I have to do it with a temp table?
Thanks in advance!

Subqueries were quite not well supported with MySQL 4.0 : it became possible to use them (at least, in some real, useful way) with MySQL 4.1 -- and MySQL 4.0 is really old, now...
See for instance this page of the MySQL manual : 12.2.8. Subquery Syntax (quoting, emphasis mine) :
Starting with MySQL 4.1, all subquery forms and operations that the
SQL standard requires are supported,
as well as a few features that are
MySQL-specific.
With MySQL versions prior to 4.1, it
was necessary to work around or
avoid the use of subqueries. In
many cases, subqueries can
successfully be rewritten using joins
and other methods. See Section
12.2.8.11, “Rewriting Subqueries as Joins for Earlier MySQL Versions”.

take out ", count(areaID) AS count"
The multiple columns in the subquery is messing up the join.
A temp table should work fine ....
Have fun!

Only thing I could think of is adding the tablename to your areaID in the subquery or renaming the reserved word count to cnt.
SELECT m_area.id
, m_area.cn_areaName
, m_area.de_areaName
, m_area.en_areaName
,m_area.jp_areaName
,t_shop.cnt
FROM m_area
left join (
select t_shop.areaID
, count(t_shop.areaID) AS cnt
from t_shop
group by t_shop.areaID
) t_shop on m_area.id = t_shop.areaID

Related

Getting syntax error for WITH RECURSIVE (MySQL 8.0.27 version)

I keep getting a syntax error "WITH is not valid input in this position" for WITH RECURSIVE. I've seen a similar problem here, where people back in 2018 said MySQL will support CTE's in MySQL version 8. Some other sources also refer that CTE should work for MySQL since version 8.0. My current version is 8.0.27, however, I still can't use WITH RECURSIVE in MySQL Workbench.
The query I need to retrieve the family tree is:
WITH RECURSIVE family_path (individual_id, first_name, path) AS
(
SELECT individual_id, first_name, first_name as path
FROM individual
WHERE parent IS NULL
UNION ALL
SELECT c.individual_id, c.first_name, CONCAT(fp.path, ' > ', c.first_name)
FROM family_path AS fp JOIN individual AS c
ON fp.individual_id = c.parent
)
SELECT * FROM family_path
ORDER BY path;
Is there any way for me to solve this problem?

Issue with a mysql query going from MySQL to MariaDB

I'm currently porting a website from PHP 5 using old mysql functions, so I basically started by replacing all of the mysql functions with the new mysqli ones and instantly got rid of most of the issues. The thing is, there is a mysql query that doesn't work anymore and I don't understand why, here is what it looks like:
SELECT *
FROM {
OJ `tableA`.`tableA`
LEFT OUTER JOIN `tableB`.`tableB` ON `tableA`.`idA` = `tableB`.`idA`
}
LEFT JOIN tableC ON tableC.idC = tableB.idC
LEFT JOIN tableD ON tableD.idD = tableC.idC
WHERE something in ('tableA','tableB')
ORDER BY column1, column2
Error says:
"Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LEFT JOIN tableC ON tableC .idC = tableB.idC' at line 6"
I want to say that I did not make the website nor I know who made it, I'm just in charge of porting it to the newer version of PHP. So I can't say for sure what this query is about, but I didn't think I would encounter such problem.
Also, I'm not familiar with this OJ {} writing so I'm not sure how I could replace it in case it was the issue here.
OPs fix for MariaDB was:
SELECT *
FROM tableA
LEFT OUTER JOIN tableB.tableB ON tableA.idA = tableB.idA
LEFT JOIN tableC ON tableC.idC = tableB.idC
LEFT JOIN tableD ON tableD.idD = tableC.idC
WHERE something in ('tableA','tableB')
ORDER BY column1, column2
Ok I fixed it by removing the curly braces and OJ and writting simply FROM tableA .... – Simon 13 mins ago
The MariaDB parser seems to only have a single table_ref in the braces.
The MySQL manual and also parser has a boarder definition.
If you which for MariaDB to support the wider format you can create a bug report

How to give an index hint to MySQL through Ecto

I need to hint an index to MySQL in a left join through Ecto and it's being pretty difficult.
The closest I've got is this:
query = from(s in Dossier.School,
left_join: sc in fragment("subscription_coordinators use index (subscription_coordinators_school_products_idx)"),
on: fragment("school_id = ?", 1)
and fragment("product in ('reading', 'maths')")
and is_nil(sc.deleted_at),
select: s,
where: s.id == 1
)
# Ecto.Adapters.SQL.to_sql(:all, Dossier.Repo, query)
query |> Dossier.Repo.all
in IEx that compiles and generates SQL fine:
SELECT s0.`id`, s0.`name`, s0.`school_code`, s0.`deleted_at`, s0.`district_id`
FROM `schools` AS s0
LEFT OUTER JOIN (subscription_coordinators use index (subscription_coordinators_school_products_idx)) AS f1 ON (school_id = 1 AND product in ('reading', 'maths')) AND f1.`deleted_at` IS NULL WHERE (s0.`id` = 1)
but obviously the position of the table alias is wrong so actually running the query produces:
** (Mariaex.Error) (1064): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'f1 ON (school_id = 1 AND product in ('reading', 'maths')) AND f1.`deleted_at` IS' at line 1
(ecto) lib/ecto/adapters/sql.ex:436: Ecto.Adapters.SQL.execute_and_cache/7
(ecto) lib/ecto/repo/queryable.ex:130: Ecto.Repo.Queryable.execute/5
(ecto) lib/ecto/repo/queryable.ex:35: Ecto.Repo.Queryable.all/4
The full query is much bigger with nearly a dozen left joins (though this is the only one that needs a hint) and all in Ecto. I want to keep the fragment as small as possible if it can be done.
This is only a temporary solution though. We'll ANALYZE TABLES soon so it's unnecessary.
It is not supported currently. Please open up an issue in the Ecto repository and we will discuss it. Thank you!

Issue with a subquery MySQL 5.5 vs 5.6

I have been running a website on MySQL 5.5 (percona) and using this query, which works:
SELECT
bds.FromStationPositionID
FROM
BusDestinationSegments AS bds
LEFT JOIN BusDestinationSegmentPrices AS bdsp ON bds.SegmentID = bdsp.BusDestinationSegmentID
AND EXISTS (
SELECT
BusDestinationScheduleID
FROM
BusDestinationSchedule
WHERE
BusDestinationScheduleDate + INTERVAL bdssf.DayOfset DAY = '2016-01-26'
),
BusDestinationStations AS bdssf
I needed to upgrade to 5.6 (again Percona) so I just did (on a development server).
However, this query now does not work. It tells me:
[Err] 1054 - Unknown column 'bdssf.DayOfset' in 'where clause'
I should add that I've checked and the column is there.
I'm guessing there is some kind of change from 5.5 to 5.6 which does not allow me to use columns in sub-queries, but I can't find anything on the topic.
Has anyone had any experience with this or can anyone suggest a way that what I'm trying to accomplish will work ?
You appear to be using a mix of old and new JOIN syntax. And expecting BusDestinationStations (which is bdssf from which the DayOfset column comes) to CROSS JOIN.
This used to work but one of the changes in MySQL 5.6 is to the precedence of the joins:-
http://dev.mysql.com/doc/refman/5.6/en/join.html :-
Previously, the comma operator (,) and JOIN both had the same
precedence, so the join expression t1, t2 JOIN t3 was interpreted as
((t1, t2) JOIN t3). Now JOIN has higher precedence, so the expression
is interpreted as (t1, (t2 JOIN t3)). This change affects statements
that use an ON clause, because that clause can refer only to columns
in the operands of the join, and the change in precedence changes
interpretation of what those operands are.
So I think what is happening is that MySQL is trying to perform the processing of the sub query before the implicit join to BusDestinationStations, and as such it doesn't know anything about bdssf.DayOfset when the sub query is executed.
Think the following would be the equivalent of what you are trying to do:-
SELECT bds.FromStationPositionID
FROM BusDestinationSegments AS bds
CROSS JOIN BusDestinationStations AS bdssf
LEFT JOIN BusDestinationSegmentPrices AS bdsp ON bds.SegmentID = bdsp.BusDestinationSegmentID
AND EXISTS
(
SELECT BusDestinationScheduleID
FROM BusDestinationSchedule
WHERE BusDestinationScheduleDate + INTERVAL bdssf.DayOfset DAY = '2016-01-26'
)
(although I am a bit dubious about doing a cross join like that just to get values for the sub query - looks very inefficient).

MySql subquery error with delete statement

I'm learning sql from these wikibooks pages and I'm trying to answer the last question "Remove all boxes from saturated warehouses" using mysql syntax. The following is what I came up with on my own mainly using previous answers from the same page.
delete from Boxes as b
where b.Warehouse in (
select w.Code
from ( select *
from Warehouses) as w
where w.Capacity < ( select count(*)
from Boxes bb inner join Warehouses ww
on bb.Warehouse = ww.Code
group by bb.Contents) ) ;
The query for this question on the site is generating
this solution doesn't work with mysql 5.0.67
ERROR 1093 (HY000): You can't specify target table 'Boxes' for update in FROM clause
That's why I'm using multiple sub queries as a way to come around this mysql message. However, I have an error in my query and therefore it's not running.
Error Code: 1064. You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'as b where b.Warehouse in ( select w.Code
from ( sel' at line 1
Any idea?
I assume Boxes and Warehouse are tables, you gave Boxes an alias and used it on the Warehouse table, that's probably why it didn't work. Maybe you should try with a query after 'delete from'.
I think your warehouses table returns from than one columns (since * is used). Replace * with the column u want to get the output from.