Mysql: seleziona le righe di una tabella che non si trovano in un'altra


118

Come selezionare tutte le righe in una tabella che non compaiono in un'altra?

Tabella 1:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Tavolo 2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
+-----------+----------+------------+

Output di esempio per le righe in Table1 che non sono in Table2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Forse qualcosa del genere dovrebbe funzionare:

SELECT * FROM Table1 WHERE * NOT IN (SELECT * FROM Table2)

Risposte:


96

Se hai 300 colonne come hai menzionato in un altro commento e vuoi confrontare su tutte le colonne (supponendo che le colonne abbiano tutte lo stesso nome), puoi usare a NATURAL LEFT JOINper unire implicitamente tutti i nomi di colonna corrispondenti tra le due tabelle in modo da non è necessario digitare noiosamente tutte le condizioni di join manualmente:

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL

Notare che questo funziona come previsto solo quando nessuna delle colonne ha valori NULL. In MySQL NULL! = NULL quindi ogni riga che ha un valore NULL verrà restituita anche se c'è una riga duplicata nella seconda tabella.
Kyle Kochis

84
Se hai 300 colonne, dovresti riprogettare il tuo database.
Iharob Al Asimi

hey funziona anche per me, grazie! ma sarebbe un problema se le righe sono> 300 come hai menzionato sopra?
thekucays

sono ancora confuso circa la query btw .. cosa succede se cambio "dove b.FirstName è nullo" in "dove b.LastName è nullo" per esempio? qual è la differenza? mi dispiace per
averlo

184

Devi fare la sottoselezione in base al nome di una colonna, non *.

Ad esempio, se avessi un idcampo comune a entrambe le tabelle, potresti fare:

SELECT * FROM Table1 WHERE id NOT IN (SELECT id FROM Table2)

Fare riferimento alla sintassi della sottoquery MySQL per ulteriori esempi.


1
grazie per il chiarimento! ma non ho davvero bisogno di basare la selezione delle righe su alcun campo, perché sono interessato a qualsiasi variazione di qualsiasi campo nella riga ...

Se ci sono solo poche colonne da confrontare puoi fare un join come nell'esempio di @ Steve. Se in realtà stai chiedendo un confronto generale dei dati in due tabelle con molte colonne, probabilmente vorrai cercare uno strumento di differenze MySQL .
Stennie

2
Nota che questo restituirà sempre un set vuoto se la colonna che stai guardando in Table2 contiene valori nulli. Non è un problema se lo fai in base alla chiave primaria, ma è rilevante per le persone che cercano di utilizzare questa query in altri contesti.
Mark Amery

4
Ma cosa succede se stiamo parlando di big data? E Table2 contiene 100 milioni di righe, ad esempio?
aggiorna

Risposta intelligente e intelligente. Grazie
amico

44
SELECT *
FROM Table1 AS a
WHERE NOT EXISTS (
  SELECT *
  FROM Table2 AS b 
  WHERE a.FirstName=b.FirstName AND a.LastName=b.Last_Name
)

EXISTS ti aiuterò...


2
Buona risposta, economica per grandi set di dati, grazie.
ekerner

Forte. Migliore risposta per set di dati di grandi dimensioni
Ian Chadwick,

35

Un LEFT JOIN standard potrebbe risolvere il problema e, se i campi sul join sono indicizzati,
dovrebbe anche essere più veloce

SELECT *
FROM Table1 as t1 LEFT JOIN Table2 as t2 
ON t1.FirstName = t2.FirstName AND t1.LastName=t2.LastName
WHERE t2.BirthDate Is Null

va bene, immagino debba essere così, btw perché WHERE t2.Birthdate Is Nullinvece di AND t1.Birthdate = t2.Birthdate?

Perché se lo aggiungi, verrà restituita ogni riga, dici che nell'output dovrebbero apparire solo le righe non nella seconda tabella
Steve

1
Questa è una risposta eccezionale, poiché non richiede la restituzione di tutte le righe di Table2!
dotancohen

Sono d'accordo, ottima risposta. Ho un tavolo a molte persone tra 4 tavoli, mettere l'AND nell'unione interna sarà sicuramente più economico.
DR.

6

Provare:

SELECT * FROM table1
    LEFT OUTER JOIN table2
    ON table1.FirstName = table2.FirstName and table1.LastName=table2.LastName
    WHERE table2.BirthDate IS NULL

4

Prova questa semplice query. Funziona perfettamente.

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);

-3

Questo ha funzionato per me in Oracle:

SELECT a.* 
    FROM tbl1 a 
MINUS 
SELECT b.* 
    FROM tbl2 b;

La domanda riguardava MySQL.
jelder

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.