Ordering clauses of a left join - mysql

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)

Related

Group by Use Query if SQL LEFT JOIN is performed multiple times

I think it's impossible, but I'm asking if there's a good way.
There are A table / B table / C table.
The table was joined LEFT JOIN based on table A with FK called id of each table.
At this time, I would like to output the count(*) as B table rows and C table rows based on b.id(B_CNT) c.id(C_CNT)
SELECT
*
FROM
A
LEFT JOIN B ON A.ID = B.ID
LEFT JOIN C ON A.ID = C.ID (base query)
how could I count group by b.id and c.id?
You could try:
SELECT
COUNT(DISTINCT B.ID), COUNT(DISTINCT C.ID)
FROM A
LEFT JOIN B
ON A.ID = B.ID
LEFT JOIN C
ON A.ID = C.ID
(I couldn't quite understand from your question, but I'm making an assumption that you want the distinct count of "ID" from each table)
You can use a couple of scalar subqueries. For example:
select id,
(select count(*) from b where b.id = a.id) as b,
(select count(*) from c where c.id = a.id) as c
from a

Does this count as an SQL LEFT OUTER JOIN?

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;

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

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;

Table identifiers with LEFT JOIN

How does one join say, on tableD.id = tableC.id AND tableD.id = tableE.id? both tableD and E may have 0 rows and I need to count them ie. SELECT COUNT(E.id). The problem is I don't know where to declare the table identifiers.
I've tried:
FROM tableB B, tableD D, tableE E ...
LEFT JOIN (tableC C, tableD D) ON ...
SELECT B.*, COUNT(C.id) AS cCount
FROM tableB B
LEFT JOIN (tableC C)
ON (B.id = C.id)
GROUP BY B.id
It is a little difficult to tell from your question what you're looking for, but I believe this is it:
SELECT B.*, COUNT(C.id) AS cCount
FROM tableB AS B
LEFT JOIN tableC AS C ON B.id = C.id
LEFT JOIN tableD AS D ON C.Id = D.Id
LEFT JOIN tableE AS E ON D.Id = E.Id
GROUP BY B.id