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.