Does this count as an SQL LEFT OUTER JOIN? - mysql

Does the following query count as an MySQL update statement with a left outer join where I'm left joining table B to table A on state and id? Or do I have to specify "left outer join B on"?
Is this correct?
UPDATE A
SET A.CITY = B.CITY
FROM B WHERE A.STATE = B.STATE
AND A.ID = B.ID;
Or does it have to be like this?
UPDATE A
SET A.CITY = B.CITY
FROM A LEFT OUTER JOIN B ON A.STATE = B.STATE
AND A.ID = B.ID;

MySQL does support multi-table UPDATE syntax. This is not standard ANSI/ISO SQL, but MySQL implements it as an extension to the standard (vendors do this frequently).
But the syntax you show doesn't match the syntax supported by MySQL. Read the following reference documentation to see the syntax:
https://dev.mysql.com/doc/refman/8.0/en/update.html
https://dev.mysql.com/doc/refman/8.0/en/join.html
The following is an inner join, which will only update rows in A when there is a matching row in B.
UPDATE A JOIN B
SET A.CITY = B.CITY
WHERE A.STATE = B.STATE AND A.ID = B.ID;
You can also write the same inner join this way:
UPDATE A JOIN B
ON A.STATE = B.STATE AND A.ID = B.ID
SET A.CITY = B.CITY;
The following is a left outer join, which will update all rows in A, even if there is no matching row in B. In those cases, it will set A.CITY = NULL.
UPDATE A LEFT OUTER JOIN B
ON A.STATE = B.STATE AND A.ID = B.ID;
SET A.CITY = B.CITY;

Related

Ordering clauses of a left join

I'm trying to join some tables with a query like below. Because I want to get the c.name ideally that the b table refers to. If the b table doesn't have rows in the result set or the b row doesn't refer to c, then just get the c.name that a table refers to.
SELECT a.*, c.name
FROM a
LEFT JOIN b ON a.b_id = b.id
LEFT JOIN c ON (b.c_id IS NOT NULL AND b.c_id = c.id) OR a.c_id = c.id
However mysql is always joining c with a.c_id = c.id and getting the less-favored c.name. Is it possible to avoid this, or is mySQL trying to get a full result set as quick as it can?
Try this may help:
SELECT a.*, c.name
FROM a
LEFT JOIN b ON a.b_id = b.id
LEFT JOIN c ON (b.c_id IS NOT NULL OR b.c_id = c.id) OR a.c_id = c.id
I think this should help:
SELECT a.*, c.name
FROM a
LEFT JOIN b ON a.b_id = b.id
LEFT JOIN c ON c.id = COALESCE(b.c_id, a.c_id)
When b.c_id is NULL, then a.c_id will be used. Otherwise b.c_id will be used.
It's not about speed. OR will give you all possible result rows including both b.c_id and a.c_id mappings for each row in a.
If you're not familiar with COALESCE(), the long form of this is almost exactly like your query but using IF() instead of OR.
SELECT a.*, c.name
FROM a
LEFT JOIN b ON a.b_id = b.id
LEFT JOIN c ON IF(b.c_id IS NOT NULL, b.c_id = c.id, a.c_id = c.id)

SQL find children that have multiple parent records

I have a situation where we have inserted duplicated data into some tables.
Given the following database schema, I want to find all records with s_id and co_id combinations associated to more than 1 record from table A. The highlighted rows are the rows I'm looking for, based off of finding the duplicates I need to find the id's from table A associated to the duplicate records.
I'm able to group by s_id & co_id to determine potential duplicates, but because Table B is a 1:M, this isn't entirely accurate.
Select c.s_id, c.co_id, Count(*)
from c
INNER JOIN b on c.b_id = b.id
INNER JOIN a on a.id = b.a_id
Group By c.s_id, c.co_id
Having count(*) > 1;
I think you just want count(distinct):
Select c.s_id, c.co_id, Count(distinct a.id)
from c join
b
on c.b_id = b.id join
a
on a.id = b.a_id
Group By c.s_id, c.co_id
having count(distinct a.id) > 1;
Gordon's answer will get you the s_id and co_id values. If you need to trace those back to a then try this:
select distinct a.id
from
a inner join b on b.a_id = a.id inner join c on c.b_id = b.id inner join
(
select c.s_id, c.co_id
from a inner join b on b.a_id = a.id inner join c on c.b_id = b.id
group by c.s_id, c.co_id
having count(distinct a.id) > 1
) as dups
on dups.s_id = c.s_id and dups.co_id = s.co_id

Join Three Tables On Two Columns

I'm using this to join 3 tables
FROM TABLE_A LEFT JOIN TABLE_B ON A.Name = B.Name
LEFT JOIN TABLE_C ON A.Name = C.Name
Whenever I try something like
FROM TABLE_A LEFT JOIN TABLE_B ON A.Name = B.Name, A.Number = B.Number
LEFT JOIN TABLE_C ON A.Name = C.Name, A.Number = C.Number
It tells me I can only use one column for this operation. I need to join on two different columns though so I can't leave it at the first example. Using AND didn't help me either.
Try to replace the comma between the dual tests with an operator.
such as:
FROM TABLE_A LEFT JOIN TABLE_B ON A.Name = B.Name AND A.Number = B.Number
LEFT JOIN TABLE_C ON A.Name = C.Name AND A.Number = C.Number

MySQL: How to skip where statement when the matched data does not exist

For example, I execute this MySQL statement
SELECT table1.a, table2.b, table3.c FROM table1, table2, table3
WHERE
a.id = b.id
AND
a.id = c.id
When there are some rows where a.id = b.id but no rows where a.id = c.id in this case,
no rows are shown in the result.
So, I want to make SQL to ignore a.id = c.id statement and show only rows that a.id = b.id is true.
Could you tell me how to do this? Thank you.
You should always use explicit join syntax. A simple rule: never use commas in the from clause.
Your query, properly written, is:
SELECT table1.a, table2.b, table3.c
FROM table1 a join
table2 b
on a.id = b.id join
table3 c
on a.id = c.id;
I notice the table aliases you use (a', b, and c) are the same as the column names. This is unusual, but allowed.
If you want to keep the records from a, then switch to left join:
SELECT table1.a, table2.b, table3.c
FROM table1 a left join
table2 b
on a.id = b.id left join
table3 c
on a.id = c.id;
This syntax is superior to the implicit join because it supports outer joins. Most people also think it is also more readable and clearer.

Fix inefficient and difficult query

I have a query in my application that is performing poorly. I think it can be optimzed but my SQL skills are failing me. Here's the query in a sort of meta-sql:
SELECT A.Value, count(*)
FROM B
JOIN A ON B.A_ID = A.ID
JOIN C ON C.ID = B.C_ID
WHERE B.C_ID IN (
SELECT B.C_ID
FROM C
JOIN B ON B.C_ID = C.ID
JOIN A ON B.A_ID = A.ID
WHERE A.VALUE IN 'string literal'
)
GROUP BY A.VALUE
C is a table of vacancies, B is a table of properties of the vacancies and A is a table of property values. The tables have 1 to N relationships. We need to find a list of all other property values (and the number of times they occur) of vacancies that have a certain fixed property value related to it.
Please help in optimizing the query for efficiency.
Thanks in advance!
You don't need to join in C in either query, unless that is being used for filtering (that is, non matches are being filtered out). Try this:
SELECT A.Value, count(*)
FROM B JOIN
A
ON B.A_ID = A.ID
WHERE EXISTS (SELECT 1
FROM B b2 JOIN
A a2
ON b2.A_ID = a2.ID
WHERE a2.VALUE = 'string literal' AND b2.C_ID = b.C_ID
)
GROUP BY A.VALUE;