2010-11-12 37 views
5

Tôi có hai bảng A và B. A là phụ huynh của B. Tôi đang cố gắng tìm tất cả Vì không có B cụ thể khi còn nhỏ. Thông thường tôi sẽ làmSQL Chọn hàng và loại trừ trẻ em

SELECT A.id FROM A 
    WHERE A.id NOT IN 
     (SELECT B.AId FROM B WHERE B.someFK = foo);

Tuy nhiên vì lý do hiệu suất, tôi không muốn sử dụng lựa chọn bên trong. Tôi đã thử một cái gì đó như:

SELECT A.id FROM A 
    LEFT JOIN B ON (A.id = B.AId) 
    WHERE B.someFK != foo OR B.someFK IS NULL

Vấn đề là này trả Như có nhiều hơn một đứa trẻ không phân biệt nếu họ có B. quy định

EDIT: Changed B.id đến B. someFK

+0

Rất tiếc, không nghĩ rằng nó sẽ tạo sự khác biệt cho ví dụ nhưng B.id phải là B.someFK. Có nghĩa là As có thể chia sẻ foo bị loại trừ. – Jim

+0

bạn có lẽ nên chỉnh sửa trực tiếp trong câu hỏi để nó đáng chú ý hơn đối với người đọc mới. – DMA57361

+0

bạn mới sử dụng StackOverflow. Vui lòng chấp nhận câu trả lời nếu nó giải quyết được vấn đề của bạn. – Falcon

Trả lời

1

Tôi muốn đi với mệnh đề tồn tại, vì nó đã được thực hiện cho một mục đích như:

SELECT A.id FROM A WHERE NOT EXISTS (SELECT 1 FROM B WHERE B.id = foo and B.AId=a.id); 

Trong hầu hết các cơ sở dữ liệu nó có hiệu suất cao hơn mệnh đề in (mà về cơ bản là một mảng để so sánh) với các tập bản ghi lớn.

Tổng hợp cũng rất tốn kém, do đó, sử dụng câu lệnh exists là cách để thực hiện. Tuy nhiên, bạn có thể thử tổng hợp cho kịch bản của mình.

0

Thử sử dụng giới hạn MAX trên bảng cha của bạn. Tôi đã không được sử dụng MySql trong một thời gian, nhưng điều này sẽ cho bạn những ý tưởng

1

bạn LEFT JOIN sẽ trở lại một hàng cho mỗi A-B liên kết (hoặc một hàng cho một A không có liên kết đến B), và sau đó loại bỏ các liên kết mà không phù hợp với tiêu chí của bạn - để lại đằng sau tất cả các liên kết khác mà đặc biệt A có trong B, đó không phải là những gì bạn muốn.

Tuy nhiên, tôi nghĩ rằng lựa chọn bên trong là cần thiết.
Nhưng có lẽ thử một EXISTS thay vì:

SELECT A.id 
FROM A 
WHERE NOT EXISTS (SELECT * FROM B WHERE B.AId = A.id AND B.someFK = foo); 
0

Hãy thử điều này

SELECT DISTINCT A.id FROM A 
LEFT JOIN B ON (A.id = B.AId) 
WHERE B.id != foo OR B.id IS NULL 
+0

hiệu suất khôn ngoan là một lựa chọn tồi, với sự tham gia và khác biệt. – Falcon

0

Bạn nên đưa toàn bộ các tiêu chí trong LEFT JOIN.

Theo như các hàng trùng lặp có liên quan, chỉ cần xác định nó.

SELECT DISTINCT A.id 
FROM A 
LEFT JOIN B 
ON A.id = B.AId AND B.someFK = "foo" 
WHERE B.AId IS NULL 
Các vấn đề liên quan