it-swarm.com.de

Markieren Sie Zeilen, die nicht in einer anderen Tabelle vorhanden sind

Ich habe zwei Postgresql-Tabellen: 

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

Ich möchte jede IP-Adresse von login_log erhalten, die keine Zeile in ip_location enthält.
Ich habe diese Abfrage ausprobiert, aber es wird ein Syntaxfehler ausgegeben.

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`

Ich frage mich auch, ob diese Abfrage (mit Anpassungen, damit sie funktioniert) die beste Abfrage für diesen Zweck ist.

118
stUrb

Es gibt im Wesentlichen 4 Techniken für diese Aufgabe, alle Standard-SQL.

NOT EXISTS

In Postgres oft am schnellsten. 

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
   );

Bedenken Sie auch:

LEFT JOIN / IS NULL

Manchmal ist das am schnellsten. Oft am kürzesten Häufig ergibt sich derselbe Abfrageplan wie bei 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

Kurz. Nicht so einfach in komplexere Abfragen zu integrieren.

SELECT ip 
FROM   login_log

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

Beachten Sie, dass ( pro Dokumentation ):

duplikate werden eliminiert, sofern nicht EXCEPT ALL verwendet wird.

Normalerweise benötigen Sie das Schlüsselwort ALL. Wenn es Ihnen egal ist, verwenden Sie es immer noch, da es die Abfrage schneller macht.

NOT IN

Nur gut ohne NULL-Werte oder wenn Sie NULL richtig handhaben können. Ich würde nicht für diesen Zweck verwenden. Die Leistung kann sich bei größeren Tabellen verschlechtern.

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

NOT IN trägt auf beiden Seiten eine "Falle" für NULL-Werte:

Ähnliche Frage zu dba.SE für MySQL:

287

A) Der Befehl ist NICHT EXISTEN, das "S" fehlt.

B.) Verwenden Sie stattdessen NOT IN

SELECT ip 
  FROM login_log 
  WHERE ip NOT IN (
    SELECT ip
    FROM ip_location
  )
;
3
caleb.breckon

das kann man auch probieren ...

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
0
Ahnaf

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 ;

Hier enthält die Testcases1-Tabelle alle Daten und die Execution1-Tabelle enthält einige Daten zwischen der Testcases1-Tabelle. Ich rufe nur die Daten ab, die nicht in der Tabelle exections1 vorhanden sind. (und selbst ich gebe einige Bedingungen an, die Sie auch angeben können.) Geben Sie die Bedingung an, die beim Abrufen von Daten nicht vorhanden sein sollte, in Klammern. 

0
Deepak N