Về cơ bản có 4 kỹ thuật cho tác vụ này, tất cả đều là SQL tiêu 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:
- Điều gì dễ đọc hơn trong các truy vấn phụ EXISTS?
LEFT JOIN / IS NULL
Đôi khi điều này là nhanh nhất. Thường ngắn nhất. Thường dẫn đến cùng một kế hoạch truy vấn là 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):
các bản sao bị loại trừ trừ khi
EXCEPT ALL
được sử dụng.
Thông thường, bạn sẽ muốn ALL
từ khóa. Nếu bạn không quan tâm, hãy 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ó NULL
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ể kém đ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 IN
mang một "cái bẫy" cho NULL
giá trị ở hai bên:
- Tìm các bản ghi mà sự tham gia không tồn tại
Câu hỏi tương tự trên dba.SE được nhắm mục tiêu vào MySQL:
- Chọn các hàng không có giá trị của cột thứ hai trong cột đầu tiên