Chọn các hàng không có trong bảng khác


172

Tôi đã có hai bảng postgresql:

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

Tôi muốn nhận mọi địa chỉ IP login_logmà từ đó không có hàng ip_location.
Tôi đã thử truy vấn này nhưng nó ném một lỗi cú pháp.

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`

Tôi cũng tự hỏi nếu truy vấn này (có điều chỉnh để làm cho nó hoạt động) là truy vấn thực hiện tốt nhất cho mục đích này.

Câu trả lời:


385

Về cơ bản có 4 kỹ thuật cho nhiệm vụ này, tất cả đều là SQL chuẩn.

NOT EXISTS

Thường nhanh nhất trong 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
   );

Cũng xem xét:

LEFT JOIN / IS NULL

Đôi khi điều này là nhanh nhất. Thường ngắn nhất. Thường kết quả trong cùng một kế hoạch truy vấn như 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

Ngắn. Không dễ dàng tích hợp trong các truy vấn phức tạp hơn.

SELECT ip 
FROM   login_log

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

Lưu ý rằng ( theo tài liệu ):

trùng lặp được loại bỏ trừ khi EXCEPT ALLđược sử dụng.

Thông thường, bạn sẽ muốn ALLtừ khóa. Nếu bạn không quan tâm, vẫn sử dụng nó vì nó làm cho truy vấn nhanh hơn .

NOT IN

Chỉ tốt mà không có NULLgiá trị hoặc nếu bạn biết xử lý NULLđúng. Tôi sẽ không sử dụng nó cho mục đích này. Ngoài ra, hiệu suất có thể xấu đi với các bảng lớn hơn.

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

NOT INmang một "cái bẫy" cho NULLcác giá trị ở hai bên:

Câu hỏi tương tự trên dba.SE nhắm vào MySQL:


2
SQL nào sẽ chạy nhanh hơn khi xem xét khối lượng dữ liệu cao trong cả hai bảng. (giả sử bằng tiền tỷ)
Teja

NGOẠI TRỪ TẤT CẢ là nhanh nhất đối với tôi
Dan Parker

Hãy cẩn thận với LEFT JOIN- nếu có nhiều hàng khớp trong bảng tra cứu, điều này sẽ tạo ra một mục trùng lặp trong truy vấn chính của bạn cho mỗi hàng phù hợp, có thể không muốn.
Matthias Fripp

@MatthiasFripp: Ngoại trừ việc điều này không bao giờ có thể xảy ra WHERE i.ip IS NULL, có nghĩa là không có trận đấu nào cả.
Erwin Brandstetter

@ erwin-brandstetter: Điểm tốt. Tôi vấp ngã khi nghĩ về khả năng có nhiều trận đấu tích cực, nhưng tất nhiên những điều đó sẽ bị loại trừ.
Matthias Fripp

2

A.) Lệnh KHÔNG phải là EXISTS, bạn đang thiếu 'S'.

B.) Sử dụng KHÔNG VÀO thay thế

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

4
KHÔNG VÀO trên các tập dữ liệu lớn là một ý tưởng khủng khiếp. Rất, rất chậm. Đó là xấu và nên tránh.
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 ;

Ở đây bảng testcase1 chứa tất cả các dữ liệu và bảng executions1 chứa một số dữ liệu trong bảng testcase1. Tôi chỉ lấy các dữ liệu không có trong bảng ex1. (và thậm chí tôi đang đưa ra một số điều kiện bên trong mà bạn cũng có thể đưa ra.) chỉ định điều kiện không nên có trong việc truy xuất dữ liệu nên nằm trong dấu ngoặc.


0

điều này cũng có thể được thử ...

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- làm thế nào WHEREđiều kiện có thể là đúng? Ngoài ra, truy vấn phụ không phải là một truy vấn tương quan.
Istiaque Ahmed
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.