Seleziona le righe che non sono presenti in un'altra tabella


173

Ho due tabelle postgresql:

table name     column names
-----------    ------------------------
login_log      ip | etc.
ip_location    ip | location | hostname | etc.

Voglio ottenere tutti gli indirizzi IP da login_logcui non ha una riga ip_location.
Ho provato questa query ma genera un errore di sintassi.

SELECT login_log.ip 
FROM login_log 
WHERE NOT EXIST (SELECT ip_location.ip
                 FROM ip_location
                 WHERE login_log.ip = ip_location.ip)
ERROR: syntax error at or near "SELECT"
LINE 3: WHERE NOT EXIST (SELECT ip_location.ip`

Mi chiedo anche se questa query (con modifiche per farla funzionare) sia la query con le migliori prestazioni a questo scopo.

Risposte:


387

Esistono sostanzialmente 4 tecniche per questa attività, tutte standard SQL.

NOT EXISTS

Spesso più veloce in Postgres.

SELECT ip 
FROM   login_log l 
WHERE  NOT EXISTS (
   SELECT  -- SELECT list mostly irrelevant; can just be empty in Postgres
   FROM   ip_location
   WHERE  ip = l.ip
   );

Considera anche:

LEFT JOIN / IS NULL

A volte questo è il più veloce. Spesso il più corto. Spesso si ottiene lo stesso piano di query di NOT EXISTS.

SELECT l.ip 
FROM   login_log l 
LEFT   JOIN ip_location i USING (ip)  -- short for: ON i.ip = l.ip
WHERE  i.ip IS NULL;

EXCEPT

Corto. Non facilmente integrato in query più complesse.

SELECT ip 
FROM   login_log

EXCEPT ALL  -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM   ip_location;

Si noti che ( per documentazione ):

i duplicati vengono eliminati a meno che non vengano EXCEPT ALLutilizzati.

In genere, ti consigliamo la ALLparola chiave. Se non ti interessa, usalo ancora perché rende la query più veloce .

NOT IN

Buono solo senza NULLvalori o se sai gestire NULLcorrettamente. Vorrei non utilizzarlo per questo scopo. Inoltre, le prestazioni possono peggiorare con tavoli più grandi.

SELECT ip 
FROM   login_log
WHERE  ip NOT IN (
   SELECT DISTINCT ip  -- DISTINCT is optional
   FROM   ip_location
   );

NOT INporta una "trappola" per i NULLvalori su entrambi i lati:

Domanda simile su dba.SE rivolta a MySQL:


2
Quale SQL sarebbe più veloce considerando che i volumi di dati sono elevati in entrambe le tabelle. (assumendo in miliardi)
Teja

SALVO TUTTO è stato il più veloce per me
Dan Parker il

Fai attenzione LEFT JOIN: se nella tabella di ricerca sono presenti più righe corrispondenti, verrà creata una voce duplicata nella query principale per ogni riga corrispondente, che potrebbe non essere desiderata.
Matthias Fripp il

@MatthiasFripp: Tranne il fatto che ciò non può mai accadere WHERE i.ip IS NULL, il che significa che nessuna corrispondenza.
Erwin Brandstetter il

@ erwin-brandstetter: buon punto. Mi sono inciampato pensando alla possibilità di più partite positive, ma ovviamente quelle sarebbero state escluse.
Matthias Fripp,

2

A.) Il comando NON ESISTE, ti manca la 'S'.

B.) Utilizzare invece NON IN

SELECT ip 
  FROM login_log 
  WHERE ip NOT IN (
    SELECT ip
    FROM ip_location
  )
;

4
NOT IN su set di dati di grandi dimensioni è un'idea terribile. Molto, molto lento. È un male e dovrebbe essere evitato.
Grzegorz Grabek,

0

SELECT * FROM testcases1 t WHERE NOT EXISTS ( SELECT 1
FROM executions1 i WHERE t.tc_id = i.tc_id and t.pro_id=i.pro_id and pro_id=7 and version_id=5 ) and pro_id=7 ;

Qui la tabella testcases1 contiene tutti i dati e la tabella executions1 contiene alcuni dati tra la tabella testcases1. Sto recuperando solo i dati che non sono presenti nella tabella exections1. (e anche io sto dando alcune condizioni all'interno che puoi anche dare.) Specificare le condizioni che non dovrebbero esserci nel recupero dei dati dovrebbero essere tra parentesi.


0

questo può anche essere provato ...

SELECT l.ip, tbl2.ip as ip2, tbl2.hostname
FROM   login_log l 
LEFT   JOIN (SELECT ip_location.ip, ip_location.hostname
             FROM ip_location
             WHERE ip_location.ip is null)tbl2

2
WHERE ip_location.ip is null- come può WHEREmai essere vera la condizione? Inoltre, la query secondaria non è correlata.
Istiaque Ahmed,
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.