2012-06-28 24 views
14

Bất cứ ai cũng biết làm thế nào để thực hiện truy vấn như vậy trong Postgresql?NOT EXISTS khoản trong Postgresql

SELECT * 
FROM tabA 
WHERE NOT EXISTS (
    SELECT * 
    FROM tabB 
    WHERE tabB.id = tabA.id 
) 

Khi tôi thực hiện truy vấn như vậy, postgresql than phiền "ERROR: Greenplum Database does not yet support that query".

EDIT: Và làm thế nào về vấn đề này một:

SELECT * 
FROM tabA 
WHERE NOT EXISTS (
    SELECT * 
    FROM tabB WHERE tabB.id = tabA.id AND tabB.id2 = tabA.id2 
) 

EDIT:
Tôi đã thử nghiệm trong postgresql 8.2.15 cho 4 câu trả lời cung cấp bởi @ypercube. Kết luận là:

1) Đầu tiên không hoạt động trong phiên bản postgresql này, như tôi đã nói ở trên trong câu hỏi. Có thể tìm thấy thông báo lỗi ở đó.

2) Đối với ba câu trả lời còn lại, tốc độ thực hiện là: (3) TÌM KIẾM TRÊN> (4) TRỪ >> (2) KHÔNG IN.
Cụ thể, đối với các truy vấn có cùng cú pháp, (3) LEFT JOIN mất khoảng 5580ms, (4) EXCEPT mất khoảng 13502ms, và (2) NOT IN mất hơn 100000 (Thực tế là tôi không đợi sử dụng xong).
Có lý do cụ thể nào cho mệnh đề NOT IN không quá chậm?
Cheng

+2

PostgreSQL 8.2 cũ và không còn được hỗ trợ. Đã có những thay đổi lớn về cách các truy vấn 'EXISTS' và' NOT EXISTS' hoạt động kể từ đó. http://www.postgresql.org/support/versioning/ – kgrittn

+0

Nếu bạn muốn tìm các truy vấn hiệu quả nhất, tôi nghĩ bạn trước tiên phải kiểm tra các chỉ mục bạn có trên các bảng.Bạn không đề cập đến kích thước của các bảng nhưng 5 giây cho một truy vấn có nghĩa là (99%) hoặc là các bảng lớn hoặc thiếu các chỉ mục. Tôi đề nghị bạn thêm một câu hỏi mới, bao gồm các định nghĩa ('CREATE TABLE') của hai bảng, các truy vấn và các kế hoạch thực hiện. –

Trả lời

21

Có 3 (chính) cách để làm điều này loại truy vấn:

  1. NOT EXISTS tương quan subquery

  2. NOT IN subquery

  3. LEFT JOIN với IS NULL kiểm tra:

Bạn phát hiện ra rằng cách đầu tiên làm việc trong Greenplum. @Marco và @juergen cung cấp cách thứ 2. Dưới đây là một trong những thứ 3, nó có thể vượt qua những hạn chế Greenplum của:

SELECT tabA.* 
FROM 
    tabA 
    LEFT JOIN 
    tabB 
     ON tabB.id = tabA.id 
     AND tabB.id2 = tabA.id2 
WHERE tabB.id IS NULL ; 

này (cách 4) cũng hoạt động trong Postgres (hỗ trợ EXCEPT điều hành):

SELECT a.* 
FROM a 
WHERE id IN 
     (SELECT id 
     FROM a 
     EXCEPT 
     SELECT id 
     FROM b 
    ) ; 

Tested trong SQL-Fiddle (rằng tất cả 4 công việc trong Postgres).

+0

@cheng: Trong sự tò mò, điều này có hiệu quả không? –

+0

Không, không. Tôi nghĩ lý do là bộ lọc "tabB.id IS NULL" được áp dụng trước LEFT JOIN, chứ không phải sau LEFT JOIN. – cheng

+0

Làm cách nào để triển khai truy vấn này với NOT EXISTS? Bạn có thể giúp đỡ gì không? – cheng

2
SELECT * FROM tabA 
WHERE id not in (SELECT id FROM tabB) 
+0

Tôi đã cập nhật câu hỏi của mình, cách thực hiện truy vấn được cập nhật trong postgresql? – cheng

3

Phần lỗi mà bạn bỏ ra có thể chỉ bạn đi đúng hướng. Tôi nghĩ rằng nó nói "CHI TIẾT: Truy vấn chứa một truy vấn con tương quan." Vì vậy, bạn phải viết lại chúng với các truy vấn con hoặc các truy vấn phụ không tương quan.

SELECT * FROM tabA WHERE id NOT IN (SELECT id FROM tabB); 

Đối với các truy vấn thứ hai, hãy thử

SELECT * FROM tabA WHERE (id, id2) NOT IN (SELECT id, id2 FROM tabB); 
+0

Cảm ơn bạn đã trả lời sớm. Tôi đã cập nhật câu hỏi của mình. Còn truy vấn mới thì sao? – cheng

+0

Có, nó nói "Truy vấn chứa truy vấn con tương quan". Loại truy vấn này được hỗ trợ trực tiếp bởi mysql. Tôi nghĩ postgresql cũng hỗ trợ nó. – cheng

+0

postgres, với nhiều thứ phức tạp hơn, nhưng greenplum không phải vì nó phải giảm chức năng vì lý do hiệu suất. –

Các vấn đề liên quan