Veuillez m'aider avec la requête MySQL suivante, qui joint deux tables (A et B):
SELECT * from A
left join B on A.sid = B.sid
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)
AND (rYear = 2011 or rYear is null)
roleCode
est un champ du tableau A et rYear
est un champ du tableau B
L'ensemble de résultats n'est pas comme prévu. Seules 185 lignes sont retournées, mais il y a 629 lignes dans le tableau A qui correspondent à la condition where. Les lignes sans ligne correspondante dans le tableau B ne doivent-elles pas être retournées avec des valeurs nulles pour leurs champs B?
Vous ne devez pas spécifier Year dans une clause WHERE. Ceux-ci limitent vos résultats après la jointure. Vous devez spécifier Year dans une clause ON pour récupérer les enregistrements avec NULL de la table B.
SELECT * from A
left join B
on A.sid = B.sid
AND (rYear = 2011 or rYear is null)
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)
Greg, est-ce vraiment tout ce qu'il y a dans la requête?
Exemples de tableaux
create table A(rCode int, sid int);
insert A select 1,1;
insert A select 2,3;
insert A select 3,2;
insert A select 5,4;
insert A select 1,5;
create table B(rYear int, sid int);
insert B select 2011,1;
insert B select null,3;
insert B select 2011,2;
insert B select 2015,2;
Requêtes:
SELECT * from A
left join B on A.sid = B.sid
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)
AND (rYear = 2011 or rYear is null);
SELECT * from A
left join B on A.sid = B.sid AND (rYear = 2011 or rYear is null)
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5);
Les deux requêtes sont exactement les mêmes, les deux retournant:
rCode sid rYear sid
----------- ----------- ----------- -----------
1 1 2011 1
2 3 NULL 3
3 2 2011 2
5 4 NULL NULL
1 5 NULL NULL
Je suis donc surpris que la requête de Jage (la 2ème option) fonctionne pour vous mais pas votre original. Ce serait une histoire différente sans le or rYear is null
Intérieur.
Pensez à LEFT JOIN comme ceci [1]
SELECT * from A
left join B on A.sid = B.sid
Gardez tout dans A, et là où il y a correspondance dans la clause ON, conservez B sinon remplissez les colonnes B avec NULL. Ajoutez la clause WHERE [2]
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)
AND (rYear = 2011 or rYear is null);
En utilisant la sortie de [1], COUPEZ en fonction du filtre, appliqué APRÈS la jointure gauche. Avec le rYear is null
, Il devrait toujours conserver tous les enregistrements A, à condition que le filtre rCode soit mis en correspondance. Cependant, si le filtre de rYear n'est
AND (rYear in (2011,2012))
C'est une autre histoire, car là où B n'a pas été apparié, le rYear a été rempli avec NULL, ce qui ne correspondra pas au filtre rYear -> la ligne entière est supprimée, y compris l'enregistrement A. Un tel filtre sur rYear serait entré dans la clause ON comme indiqué ci-dessous, sinon il pourrait aussi bien en faire un INNER JOIN.
SELECT * from A
left join B on A.sid = B.sid AND (rYear in (2011,2012))
where (rCode = 1 Or rCode = 2 Or rCode = 3 Or rCode = 5)