web-dev-qa-db-ja.com

他のテーブルに存在しない行を選択してください

2つのpostgresqlテーブルがあります。

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

login_logに行がないip_locationからすべてのIPアドレスを取得したいのですが。
このクエリを試しましたが、構文エラーが発生しました。

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`

私はまた、このクエリ(それが機能するように調整したもの)がこの目的のための最高のパフォーマンスのクエリであるかどうか疑問に思います。

132
stUrb

このタスクには基本的に4つの技法があり、それらはすべて標準SQLです。

NOT EXISTS

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

また考えなさい:

LEFT JOIN / IS NULL

時にはこれが最速です。しばしば最短です。多くの場合、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

ショート。より複雑なクエリにそれほど簡単には統合されません。

SELECT ip 
FROM   login_log

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

そのことに注意してください( ドキュメントごと ):

EXCEPT ALLが使用されていない限り、重複は排除されます。

通常はALLキーワードが必要です。気にしなくても、クエリが高速になるため、まだ使用してください。

NOT IN

NULL値がない場合、またはNULLを適切に処理することがわかっている場合にのみ有効です。私はこの目的のためにそれを使用しません。テーブルが大きいとパフォーマンスが低下する可能性があります。

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

NOT INは、どちらの側でもNULL値に対する「トラップ」を運びます。

MySQLをターゲットにしたdba.SEに関する同様の質問:

306

A.)コマンドが存在しません、 'S'がありません。

B.)代わりにNOT INを使う

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

これも試すことができます...

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 ;

Testcases1テーブルにはすべてのデータが含まれ、executiontions1テーブルにはtestcases1テーブルの中のいくつかのデータが含まれています。 exections1テーブルに存在しないデータのみを取得しています。 (そして私もあなたが与えることができるその中にいくつかの条件を与えています。)データを検索する際にそこにあってはならない条件を大括弧で囲まなければなりません。

0
Deepak N