MySQL sélectionnez les lignes où LEFT join est null

J'ai ces tables MySQL:

Tableau1:

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

Tableau2:

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 renverra toutes les lignes de table1 qui sont 1,2,3

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

Je veux en quelque sorte le contraire de INNER JOIN qui ne sélectionnera que les lignes qui se trouvent dans la jointure. Comment obtenir le contraire comme si LEFT join existe, l'ignorer et passer à la ligne suivante. J'espère que je suis clair

21
demandé sur smoove 2014-09-17 16:26:31

6 réponses

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 fonctionnent mieux:

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;
31
répondu GarethD 2014-09-17 12:38:43

L'une des meilleures approches si vous ne voulez pas renvoyer de colonnes à partir 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 dit ce que vous voulez interroger: Sélectionnez chaque ligne où il n'y a pas d'enregistrement correspondant dans la deuxième table.

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

11
répondu Pred 2014-09-17 13:30:52

Voici une requête qui retourne uniquement les lignes où 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 cela vous aidera.

2
répondu Joël Salamin 2014-09-17 12:38:22

Essayez:

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 Démo

, 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 2ème Démo

2
répondu Edper 2014-09-17 12:49:28

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 aidera.

1
répondu Ankit Bajpai 2014-09-17 12:35:49
SELECT table1.id 
FROM table1 
LEFT JOIN table2 ON table1.id = table2.user_one
WHERE table2.user_one is NULL
1
répondu Chris 2014-09-17 12:36:59