MySQL JOIN query worked in version 4, broken in 5 - mysql

I've inherited a website someone else built using MySQL 4 as the database and am trying to switch to a new server, running MySQL 5. I copied all files across and dumped the database from MySQL version 4 and then imported back into version 5.
Now, half of the website is working while the other half is not. I keep getting the following:
Unknown column 'a.id_art' in 'on clause'
Here's my query:
SELECT *, aks.nazwa as sekcja, ak.nazwa kategoria
FROM
artykuly a,
artykuly_kategorie ak,
artykuly_sekcje aks
LEFT JOIN artykuly_addons aad ON aad.id_art=a.id_art
WHERE a.id_art = '20' AND ak.id_sek = aks.id_sek AND a.id_kat = ak.id_kat
Why does the above work fine in MySQL version 4 but is a broken man in version 5?

Probably the combination of LEFT JOIN and joining with commas and filtering in the WHERE clause causes the problem. Try this:
SELECT *, aks.nazwa as sekcja, ak.nazwa kategoria
FROM
artykuly a INNER JOIN artykuly_kategorie ak ON a.id_kat = ak.id_kat
INNER JOIN artykuly_sekcje aks ON ak.id_sek = aks.id_sek
LEFT JOIN artykuly_addons aad ON aad.id_art=a.id_art
WHERE a.id_art = '20'

The precedence of the comma is now lower than explicit JOIN statements. Quoting the MySQL 5.0 JOIN Syntax page:
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))
So previously this was treated as
SELECT *,
aks.nazwa as sekcja,
ak.nazwa kategoria
FROM
(
(
artykuly a,
artykuly_kategorie ak0
),
artykuly_sekcje aks
)
LEFT JOIN artykuly_addons aad ON aad.id_art=a.id_art
WHERE a.id_art = '20'
AND ak.id_sek = aks.id_sek
AND a.id_kat = ak.id_kat
Now it is interpreted as:
SELECT *,
aks.nazwa as sekcja,
ak.nazwa kategoria
FROM
(
(
artykuly a,
artykuly_kategorie ak0
),
(artykuly_sekcje aks LEFT JOIN artykuly_addons aad ON aad.id_art=a.id_art)
)
WHERE a.id_art = '20'
AND ak.id_sek = aks.id_sek
AND a.id_kat = ak.id_kat

Related

MySQL combine multiple SELECT and JOIN [duplicate]

I have the following MySQL query:
SELECT p.*,
IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
pm.MediaID,
date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
astext(pg.Geometry) AS Geometry
FROM property p, propertygeometry pg
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
AND p.PropertyGeometryID = pg.id
GROUP BY p.id
And I'm getting this error:
#1054 - Unknown column 'p.id' in 'on clause'
As far as I can see the query looks right, any idea what could be wrong?
Don't mix ANSI-89 style and ANSI-92 style joins. They have different precedence which can lead to confusing errors, and that is what has happened here. Your query is being interpreted as follows:
FROM property p, (
propertygeometry pg
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
...
)
In the above, the joins using the JOIN keyword are evaluated first before the comma-style join is even considered. At that point the table p isn't yet declared.
From the MySQL manual:
However, the precedence of the comma operator is less than of INNER JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with the other join types when there is a join condition, an error of the form Unknown column 'col_name' in 'on clause' may occur. Information about dealing with this problem is given later in this section.
I'd recommend always using ANSI-92 style joins, i.e. using the JOIN keyword:
SELECT p.*,
IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
pm.MediaID,
date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
astext(pg.Geometry) AS Geometry
FROM property p
JOIN propertygeometry pg ON p.PropertyGeometryID = pg.id
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
GROUP BY p.id
Related:
Why isn't SQL ANSI-92 standard better adopted over ANSI-89?
As stated before there is a precedence issue using joins via the comma operator where the LEFT JOIN will be executed and so references to table aliases won't exist at that time. Though you can implicitly tell MySQL to use a JOIN via that statement you may also tell MySQL to evaluate the comma joined tables first, then execute left join thusly:
SELECT p.*,
IF(COUNT(ms.PropertyID) > 0,1,0) AS Contacted,
pm.MediaID,
date_format(p.AvailableFrom, '%d %b %Y') AS 'AvailableFrom',
astext(pg.Geometry) AS Geometry
FROM (property p, propertygeometry pg)
JOIN shortlist sl ON sl.PropertyID = p.id AND sl.MemberID = 384216
LEFT JOIN message ms ON ms.PropertyID = p.id AND ms.SenderID = 384216
LEFT JOIN property_media pm ON pm.PropertyID = p.id AND pm.IsPrimary = 1
WHERE p.paused = 0
AND p.PropertyGeometryID = pg.id
GROUP BY p.id
Notice the comma separated tables are contained within parenthesis (). The table aliases and columns will now be available to your other JOINs.
I bumped into this error unknown column, the diff is the query is built thru HQL inside session.executeQuery("select id, name, sum(paid), custType from cust group by brand") that's why having to manually type inner join or join keyword is not an option as the hql is the one generating it.
it produces a query sumthing like this:
select cust_id, name, sum(paid), c.custTypeId
from customer c, custType ct
on c.custTypeId = ct.custTypeId
it says "unknown c.custTypeId" column when I am 101% sure it bears that column.
My classes/relations:
Customer {
Integer custId
CustomerType custType
}
CustomerType{
Integer custTypeId
string code
}
the problem lies in the comma in "from customer, custType" line. it should be with the word JOIN as the answer stated above. but since it is HQL and is being generated, I can't do that. What I did is modified by query and instead of typing select custType, I typed select custType.id, custType.code
I know it's basic but for first timers like me, it was a struggle.
If this helps someone (and a note to future myself), I was getting this error when trying to execute the following queries in MariaDB:
SELECT a.name, b.name
FROM `cities` as a
INNER JOIN `countries` as b
ON `a.country_id` = `b`.`id`;
whereas I should have written it like:
SELECT a.name, b.name
FROM `cities` as a
INNER JOIN `countries` as b
ON `a`.`country_id` = `b`.`id`;
I'll leave it to the reader to spot the difference as an exercise. :)

Mysql check if table has any value

Basically what I'm trying to do is to get a list of purchases from one table and check if there is any attachments associated with the purchase and display 1 or 0 if there is/isn't an attachment found.
SELECT
CONCAT('#', LPAD(a.id, 5, '0')) as 'code',
a.id, a.value_total, DATE_FORMAT(a.date, '%d/%m/%Y') as 'date',
b.name as 'store',
CASE WHEN a.notes IS NOT NULL
THEN 1
ELSE 0
END AS notes
FROM
tb_purchase a,
tb_store b
WHERE a.id_store = b.id
AND a.id = :id_purchase // This line can be removed to get all the purchases or leave here to get just one with that specific ID
then I have a table called ts_purchase_att where I store the attachments relation between purchases and attachments. The table has this structure:
id_purchase | id_attachment
32 | 47
32 | 127
33 | 68
38 | 97
I don't need to get the attachments, just check if there is at least one attachment related to that purchase.
I tried using something like this but it doesn't work
LEFT JOIN
( SELECT 1 FROM ts_purchase_att c WHERE c.id_purchase = a.id ) as attachment
What am I doing wrong?
Use JOIN syntax consistently, it has been standard since 1992. Don't use the outdated comma-style joins. Mixing the two syntax styles is causing a real problem in your case.
The reason is that the JOIN operation has a higher precedence than the , join. So when you do this type of query:
FROM a, b LEFT OUTER JOIN c ON a.id = c.id_purchase
It first tries to evaluate the b LEFT OUTER JOIN c, but you're referencing the first table a in the join condition. MySQL hasn't even made that table alias yet, so it returns an error on references to columns belonging to a.
This is documented here: https://dev.mysql.com/doc/refman/8.0/en/join.html
JOIN has higher precedence than the comma operator (,), so the join expression t1, t2 JOIN t3 is interpreted as (t1, (t2 JOIN t3)), not as ((t1, t2) JOIN t3). This affects statements that use an ON clause because that clause can refer only to columns in the operands of the join, and the precedence affects interpretation of what those operands are.
See that section of the manual for more details and examples.
Here's the way to do the outer join combined with inner joins using JOIN syntax:
SELECT IF(c.id_purchase IS NULL, 0, 1) AS attachment_found
FROM tb_purchase a,
INNER JOIN tb_store b ON a.id_store = b.id
LEFT OUTER JOIN ts_purchase_att c ON a.id = c.id_purchase
You need a LEFT JOIN:
SELECT DISTINCT
CONCAT('#', LPAD(a.id, 5, '0')) as 'code',
a.id, a.value_total, DATE_FORMAT(a.date, '%d/%m/%Y') as 'date'
CASE
WHEN b.id IS NOT NULL THEN 1
ELSE 0
END AS notes
FROM tb_purchase a LEFT JOIN tb_store b
ON a.id_store = b.id
When there is no match in the table tb_store then b.id is null.

Can't do 2 joins on an MS Access query?

So I have checked all the names etc are correct, the query works with only one of the joins not both with a syntax error:
SELECT *, Invoice_Accounts.Title AS t1, Invoice_Accounts.Forename AS f1, Invoice_Accounts.Surname AS s1
FROM Invoice_Accounts
RIGHT JOIN Delivery_Points ON Invoice_Accounts.Account_No = Delivery_Points.Account_No
RIGHT JOIN Companies ON Invoice_Accounts.account_id = Companies.Company_No
This is the query I want to run but it comes up with the error:
syntax error (missing operator)
UPDATE:
using:
SELECT *,
Invoice_Accounts.Title AS t1,
Invoice_Accounts.Forename AS f1,
Invoice_Accounts.Surname AS s1
FROM (Invoice_Accounts
RIGHT JOIN Delivery_Points
ON Invoice_Accounts.Account_No = Delivery_Points.Account_No)
RIGHT JOIN Companies
ON Invoice_Accounts.account_id = Companies.Company_No
Gets me the error "JOIN expression not supported"
In Access you need to use parenthesis around joins if you have more than one:
SELECT *,
Invoice_Accounts.Title AS t1,
Invoice_Accounts.Forename AS f1,
Invoice_Accounts.Surname AS s1
FROM (Invoice_Accounts
RIGHT JOIN Delivery_Points
ON Invoice_Accounts.Account_No = Delivery_Points.Account_No)
RIGHT JOIN Companies
ON Invoice_Accounts.account_id = Companies.Company_No
Two extend this, if you had three joins, you would need another set of parentheses:
SELECT *
FROM (( A
INNER JOIN B
ON B.AID = A.AID)
INNER JOIN C
ON C.BID = B.BID)
INNER JOIN D
ON D.CID = C.CID;
EDIT
I did not know that you could not RIGHT JOIN to the same table twice, so the above is an error, having said that I have never used a RIGHT JOIN in production code in my life, I would be inclined to switch to the more widely used LEFT JOIN and change the order of the tables:
SELECT *,
ia.Title AS t1,
ia.Forename AS f1,
ia.Surname AS s1
FROM (Companies AS c
LEFT JOIN Invoice_Accounts AS ia
ON ia.account_id = c.Company_No)
LEFT JOIN Delivery_Points AS dp
ON ia.Account_No = dp.Account_No;
N.B. I have used aliases to reduce the amount of text in the query, this (in my opinion) makes them easier to read
Figured out the answer eventually:
SELECT Invoice_Accounts.Title AS t1, Invoice_Accounts.Forename AS f1, Invoice_Accounts.Surname AS s1, *
FROM (Companies
RIGHT JOIN Invoice_Accounts ON Companies.Company_No = Invoice_Accounts.Company_Name
)
RIGHT JOIN Delivery_Points ON Invoice_Accounts.Account_No = Delivery_Points.Account_No;
The issue arises from ancient ms-access technologies where you can't right join to the same table more than once!

Getting data differences between two queries

I have two queries that result two result sets i need to compare both the result sets and need to display the differences between them.Hope i will get good support.Thank you.These are my queries
Query:1
SELECT distinct c.sid_ident,c.fix_ident from corept.std_sid_leg as c INNER JOIN (SELECT sid_ident, transition_ident, max(sequence_num) seq, route_type FROM corept.std_sid_leg WHERE data_supplier='J' AND airport_ident='KBOS' GROUP BY sid_ident,transition_ident) b ON c.sequence_num=b.seq and c.sid_ident = b.sid_ident and c.transition_ident =b.transition_ident WHERE c.data_supplier='J' and c.airport_ident='KBOS';
Query:2
SELECT name,trans FROM skyplan_deploy.deploy_sids ON d.name=c.sid_ident WHERE apt = 'KBOS' AND name != trans;
Comparison is to be done on fields sid_ident in corept.std_sid_leg and name in skplan_deplay.deploy_sids. As Mysql does not support full outer join,I thought of using left join and right join and combine both the results.But i stuck up with this.Please help.I am getting syntax error while using left and right join.Thank you.
The following query should simulate a FULL OUTER JOIN in MySQL.
SELECT *
FROM A
LEFT OUTER JOIN B
ON A.NAME = B.NAME
WHERE B.ID IS NULL
UNION ALL
SELECT *
FROM B
LEFT OUTER JOIN A
ON B.NAME = A.NAME
WHERE A.ID IS NULL;
Compare the results of the with an actual FULL OUTER JOIN in SQL Server and you'll see it works.

MySQL LEFT JOIN after 5.0.12 changes - How to rewrite query

After 5.0.12 MySQL changed the syntax for left joins to match SQL2003 standard. So
... FROM t1 , t2 LEFT JOIN t3 ON (expr)
needs to be rewritten as
... FROM (t1 , t2) LEFT JOIN t3 ON (expr
or else it will be parsed as ... FROM t1 , (t2 LEFT JOIN t3 ON (expr))
Now, I have an ancient app I'm porting from MySQL 3.23 (eek!) to 5.1, and the old code has this query:
select b.*, c.*, g.*, p.perfname, p.persname
from bookings b, customer c
left join grade g on b.chrggrade=g.grcode
left join person p on b.person=p.percode
where complete='Y' and invoiced='N'
and datemade between '2009-03-25' and '2009-03-31'
and c.custcode=b.cust
order by cust, person, tsref, stdt
This fails with SQL error 1054, unknown column in b.chrggrade. This is because it's parsing as
select b., c., g.*, p.perfname, p.persname
from bookings b, (customer c
left join grade g on b.chrggrade=g.grcode )
left join person p on b.person=p.percode
where complete='Y' and invoiced='N'
and datemade between '2009-03-25' and '2009-03-31'
and c.custcode=b.cust
order by cust, person, tsref, stdt
I think.
I'm sure correctly placed brackets can fix this but I'm stumped.
I found reference to this change at http://bugs.mysql.com/bug.php?id=13551, which shows how to fix a simple left join, but I still can't work it out for this query.
David
Stop using the comma syntax altogether and be explicit in your JOIN statements. The comma syntax forces you to put the JOIN condition in the WHERE clause, which may not get executed until after LEFT/RIGHT joins, depending on how it's parsed. Using explicit JOINS makes the query more readable anyway.
...FROM t1, t2 LEFT JOIN t3 ON (expr)
becomes
...FROM t1 INNER JOIN t2 ON (expr) LEFT JOIN t3 ON (expr)
That will also fix the error you are seeing. Unless there is no chrggrade in the bookings table, then nothing will fix the error.