web-dev-qa-db-fra.com

MySQL sélectionne les lignes où la jointure gauche est nulle

J'ai ces tables MySQL:

tableau 1:

id | writer
1  | Bob   
2  | Marley
3  | Michael

tableau 2:

user_one | user_two
   1     | 2

Et cette requête:

SELECT table1.id FROM table1 LEFT JOIN table2 ON table1.id = table2.user_one

Cette requête retournera toutes les lignes de la table1 qui sont 1,2,3

Je veux sélectionner uniquement les lignes qui ne se trouvent pas dans l'articulation gauche. Donc, il ne devrait retourner que row avec id 3

Je veux en quelque sorte le contraire de INNER JOIN qui ne sélectionne que les lignes qui se trouvent dans la jointure. Comment obtenir le contraire, comme si la jointure gauche existait, ignorez-la et passez à la ligne suivante. J'espère que je suis clair

24
Michael Samuel

Vous pouvez utiliser la requête suivante:

SELECT  table1.id 
FROM    table1 
        LEFT JOIN table2 
            ON table1.id IN (table2.user_one, table2.user_two)
WHERE   table2.user_one IS NULL;

Bien que, en fonction de vos index sur table2 vous pouvez constater que deux jointures donnent de meilleurs résultats:

SELECT  table1.id 
FROM    table1 
        LEFT JOIN table2 AS t1
            ON table1.id = t1.user_one
        LEFT JOIN table2 AS t2
            ON table1.id = t2.user_two
WHERE   t1.user_one IS NULL
AND     t2.user_two IS NULL;
41
GarethD

L’une des meilleures solutions si vous ne souhaitez renvoyer aucune colonne de table2 est d'utiliser le NOT EXISTS

SELECT  table1.id 
FROM    table1 T1
WHERE
  NOT EXISTS (SELECT *
              FROM table2 T2
              WHERE T1.id = T2.user_one
                  OR T1.id = T2.user_two)

Sémantiquement, cela indique ce que vous souhaitez interroger: sélectionnez chaque ligne pour laquelle il n'y a pas d'enregistrement correspondant dans la deuxième table.

MySQL est optimisé pour EXISTS: il revient dès qu'il trouve le premier enregistrement correspondant.

13
Pred

Voici une requête qui renvoie uniquement les lignes pour lesquelles aucune correspondance n'a été trouvée dans les deux colonnes user_one et user_two de table2:

SELECT T1.*
FROM table1 T1
LEFT OUTER JOIN table2 T2A ON T2A.user_one = T1.id
LEFT OUTER JOIN table2 T2B ON T2B.user_two = T1.id
WHERE T2A.user_one IS NULL
    AND T2B.user_two IS NULL

Il y a une jointure pour chaque colonne (user_one et user_two) et la requête ne renvoie que les lignes qui n'ont pas de jointure correspondante.

J'espère que ceci vous aidera.

3
Joël Salamin

Essayer:

SELECT A.id FROM
(
  SELECT table1.id FROM table1 
  LEFT JOIN table2 ON table1.id = table2.user_one
  WHERE table2.user_one IS NULL
) A
JOIN (
  SELECT table1.id FROM table1 
  LEFT JOIN table2 ON table1.id = table2.user_two
  WHERE table2.user_two IS NULL
) B
ON A.id = B.id

Voir Demo

Ou vous pouvez utiliser deux LEFT JOINS avec des alias comme:

SELECT table1.id FROM table1 
 LEFT JOIN table2 A ON table1.id = A.user_one
 LEFT JOIN table2 B ON table1.id = B.user_two
 WHERE A.user_one IS NULL
 AND B.user_two IS NULL

Voir 2nd Demo

2
Edper

Essayez la requête suivante: -

 SELECT table1.id 
 FROM table1 
 where table1.id 
 NOT IN (SELECT user_one
         FROM Table2
             UNION
         SELECT user_two
         FROM Table2)

J'espère que cela vous aide.

1
Ankit Bajpai
SELECT table1.id 
FROM table1 
LEFT JOIN table2 ON table1.id = table2.user_one
WHERE table2.user_one is NULL
1
Chris