MySQL with IF or EXISTS in WHERE - mysql

I have a problem with the following query for id’s not present in tableC. Despite the LEFT JOIN, an id in tableA and tableB is not in the results if the id is absent from tableC. And that is because the tableC.name doesn’t exist for these id’s. I imagined MySQL would then ignore the last part considering the clause to be true….but no.
SELECT
tableA.id, tableA.name
FROM
tableA
LEFT JOIN tableB ON tableA.id = tableB.id
LEFT JOIN tableC ON tableA.id = tableC.id
WHERE
tableA.latin = 'whatever'
AND RIGHT(tableC.name,2) != 'y'
I imagine there is a solution using either IF, CASE or EXISTS on the second part of the WHERE clause, but I don’t get the result I want with the following three attempts (I only show the last line):
WHERE
tableA.latin = 'whatever'
AND IF(tableC.name <> 0, RIGHT(tableC.name,2) != 'y', ' ');
This doesn’t give error either, but not the expected result:
WHERE
tableA.latin = 'whatever'
AND IF(tableC.name = true, RIGHT(tableC.name,2)!= 'y', ' ');
Trying the following with EXISTS gives me error in the MySQL Wordbench editor:
WHERE
tableA.latin = 'whatever'
AND if(EXISTS tableC.name, RIGHT(tableC.name,2) != 'y', ' ');

Any time you reference a column (tableC.name in your case) from a left-joined table in the where clause, you force the join to behave as if it were an inner join. Instead, move the test into the join condition.
SELECT tableA.id, tableA.name
FROM tableA
LEFT JOIN tableB
ON tableA.id = tableB.id
LEFT JOIN tableC
ON tableA.id = tableC.id
AND RIGHT(tableC.name,2) != 'y'
WHERE tableA.latin = 'whatever'

There is a much easier solution. Your where condition is turning the outer joins into inner joins. Just move the condition into the on clause:
SELECT tableA.id, tableA.name FROM tableA
LEFT JOIN tableB ON tableA.id = tableB.id
LEFT JOIN tableC ON tableA.id = tableC.id AND RIGHT(tableC.name, 2) <> 'y'
WHERE tableA.latin = 'whatever';
Of course, the expression RIGHT(tableC.name,2) != 'y' should always be true almost always, because you are looking for two characters and comparing to one. Perhaps you mean:
SELECT tableA.id, tableA.name FROM tableA
LEFT JOIN tableB ON tableA.id = tableB.id
LEFT JOIN tableC ON tableA.id = tableC.id AND tableC.name not like '%y'
WHERE tableA.latin = 'whatever';

How about this (untested but I think it should work):
SELECT tableA.id, tableA.name FROM tableA
LEFT JOIN tableB ON tableA.id = tableB.id
LEFT JOIN tableC ON (tableA.id = tableC.id AND RIGHT(tableC.name,2) != 'y')
WHERE tableA.latin = 'whatever'
It makes table c only include the ones you want but doesn't interfere with the left outer join.

Related

Laravel Lumen whereJsonContains not working with JOIN

Query
select tablea.*,
tableb.id as tableb_id,
tableb.name as tableb_name,
tableb.settings,
tableb.logo
from tablea
left join tableb
on tableb.id = tablea.id
left join tablec
on tablec.id = tableb.id
where json_contains(tablea.fields, '2022-07-01', '$."date"."data"')
Description: The whereJsonContains not working with join when join didn't fill requirements. If tableb didn't have an entry in the reference of table1. The query didn't revert the result.

MYSQL: UPDATE FROM INNER JOIN syntax error

I am trying to update TableA with values from TableB, matched by the unique id field and add a WHERE condition.
Searched the web and found the code below. For some reason MYSQL states that there's as syntax error.
UPDATE
TableA
SET
TableA.field1 = TableB.field1
FROM
TableA
INNER JOIN
TableB
ON
TableA.id = TableB.id
WHERE
TableA.field1 <> ''
LIMIT 100;
The correct syntax in MySQL is:
UPDATE TableA INNER JOIN
TableB
ON TableA.id = TableB.id
SET TableA.field1 = TableB.field1
WHERE TableA.field1 <> '';
As a note: you cannot use LIMIT with a JOIN.
If you want to use LIMIT, you can do:
UPDATE TableA
SET TableA.field1 = (SELECT TableB.field1 FROM TableB WHERE TableA.id = TableB.id)
WHERE TableA.field1 <> '' AND
EXISTS (SELECT 1 FROM TableB WHERE TableA.id = TableB.id)
LIMIT 100;
(You can leave out the EXISTS expression if you know there is always a match in TableB. You can add LIMIT 1 to the subquery if more than one match is possible.)
I would advise you to always use ORDER BY with LIMIT as well. That way, you can control which rows are being updated.

mysql case statement for joining three table

there is three table
table a
table b
table c
and my query is :
select a.title,a.id,b.title
from table a
case when a.type=1 then
inner join table a.id=tableb.id end
case when a.type=2 then inner join table a.id=table c.id
But this query doesnt work.Can somebody helpe the right way to fetch or execute this type of query
You cannot use case in the from clause. To achieve this you could use UNION ALL. For instance:
select a.title,a.id,b.title
from table a inner join table b on a.id=b.id
where a.type=1
UNION ALL
select a.title,a.id,c.title
from table a inner join table c on a.id=c.id
where a.type=2
You cannot do something like "if this is 1 then join other table than if it is 2", you must join both and select accordingly:
SELECT
a.title,
a.id,
IF (tableb.title IS NOT NULL, tableb.title, tablec.title),
CASE a.type
WHEN 1 THEN tableb.id
WHEN 2 THEN tablec.id
END
FROM table a
LEFT JOIN tableb ON tablea.id = tableb.id
LEFT JOIN tablec ON tablea.id = tablec.id

Looking for a query with a subquery

I have 2 tables in my database:
TableA contains aId, aBId, a3, ...
TableB contains bId, b2value, b3,...
aBId is a the bId of the tableB.
I need a mysql query that selects all the records from tableA where the record from bId has b2value = 'something'...
hate queries...
select a.*
from TableA a
inner join TableB b on a.aBid = b.bId
where b.b2Value = 'something'
select a.* from TableA a join TableB b on a.aBId = b.bId where
b.b2value = 'something'
select *
from TableA
inner join TableB on TableA.aBId = TableB.bId
where TableB.b2Value = 'something'

How sql server evaluates the multiple different joins?

i have a general question about how sql server evaluates the joins.The query is
SELECT *
FROM TableA
INNER JOIN TableB ON TableB.id = TableA.id
LEFT JOIN TABLEC ON TABLEC.id = TABLEB.id
Q1: What tables is the left join based on? I know it will based on the TABLEC but what is the other one? Is it the result of the first inner join or the TABLEB specified in the left join condition?
Q2: Is "LEFT JOIN TABLEC ON TABLEC.id = TABLEB.id" equivalent to "LEFT JOIN TABLEC ON TABLEB.id = TABLEC.id"
Q3: Is the query equivalent to the following one? (with TABLEB.id replaced by TABLEA.id?)
SELECT *
FROM TableA
INNER JOIN TableB ON TableB.id = TableA.id
LEFT JOIN TABLEC ON TABLEC.id = TABLEA.id
Thank you!
Q1: It is based on the result of the inner join, therefore it will only LEFT JOIN with items that are in TableA AND TableB.
Q2: Yes
Q3: Yes, it's a consequence of question Q1.
SQL is a declarative language. When you declare 'A JOIN B JOIN C' there is no order of join involved. The end result has to match the required criteria, but the underlying implementation is free to choose any actual implementation order.
At a logical level the inner JOIN operator is associative so the order does not matter: 'A JOIN B JOIN C' is identical with 'A JOIN C JOIN B' which is identical with 'B JOIN A JOIN C' and so on and so forth.