2009-04-15 42 views
46

Tôi có một truy vấn MySQL mà tham gia hai bảngMySQL Tham gia nơi không tồn tại

  • Cử tri
  • hộ họ tham gia vào voters.household_id và household.id

    Bây giờ những gì tôi cần làm là sửa đổi nó nơi bảng cử tri được nối với bảng thứ ba được gọi là loại bỏ, cùng với voter.id và elimination.voter_id, bao giờ bắt được là tôi muốn loại trừ bất kỳ bản ghi nào trong bảng cử tri có một bản ghi tương ứng trong việc loại bỏ bàn. làm thế nào để tôi tạo một truy vấn để làm điều này?

này là truy vấn hiện tại của tôi

SELECT `voter`.`ID`, `voter`.`Last_Name`, `voter`.`First_Name`, 
     `voter`.`Middle_Name`, `voter`.`Age`, `voter`.`Sex`, 
     `voter`.`Party`, `voter`.`Demo`, `voter`.`PV`, 
     `household`.`Address`, `household`.`City`, `household`.`Zip` 
FROM (`voter`) 
JOIN `household` ON `voter`.`House_ID`=`household`.`id` 
WHERE `CT` = '5' 
AND `Precnum` = 'CTY3' 
AND `Last_Name` LIKE '%Cumbee%' 
AND `First_Name` LIKE '%John%' 
ORDER BY `Last_Name` ASC 
LIMIT 30 

Trả lời

122

tôi có lẽ muốn sử dụng một Left Join, mà sẽ trở lại hàng ngay cả khi không có trận đấu, và sau đó bạn có thể lựa chọn chỉ các hàng với không phù hợp bởi kiểm tra NULL.

Vì vậy, một cái gì đó như:

SELECT V.* 
FROM voter V LEFT JOIN elimination E ON V.id = E.voter_id 
WHERE E.voter_id IS NULL 

Cho dù đó là nhiều hay ít hiệu quả hơn so với sử dụng một subquery phụ thuộc vào tối ưu hóa, chỉ số, cho dù nó có thể có nhiều hơn một loại bỏ mỗi cử tri vv

+8

+1 trả về nhanh hơn truy vấn phụ – ravi404

+1

+1 nhanh hơn khi tải cao rồi truy vấn phụ + nếu U có thể thực hiện JOIN thay vì truy vấn phụ - chỉ cần thực hiện JOIN chúng đơn giản hơn rất nhiều cho trình phân tích. Một ví dụ hữu ích khác, U có thể muốn nhận kết quả nếu có một số hàng trong bảng bên phải hoặc nếu không có một hàng: 'SELECT V. * TỪ cử tri V LEFT JOIN loại bỏ E ON V.id = E.voter_id OR E .voter_id IS NULL': nếu U không muốn lưu trữ tất cả các bản ghi trong bảng bên phải cho mỗi hàng từ bên trái. –

4

Tôi muốn sử dụng 'không tồn tại' - chính xác như bạn đề xuất trong tiêu đề của bạn:

SELECT `voter`.`ID`, `voter`.`Last_Name`, `voter`.`First_Name`, 
     `voter`.`Middle_Name`, `voter`.`Age`, `voter`.`Sex`, 
     `voter`.`Party`, `voter`.`Demo`, `voter`.`PV`, 
     `household`.`Address`, `household`.`City`, `household`.`Zip` 
FROM (`voter`) 
JOIN `household` ON `voter`.`House_ID`=`household`.`id` 
WHERE `CT` = '5' 
AND `Precnum` = 'CTY3' 
AND `Last_Name` LIKE '%Cumbee%' 
AND `First_Name` LIKE '%John%' 

AND NOT EXISTS (
    SELECT * FROM `elimination` 
    WHERE `elimination`.`voter_id` = `voter`.`ID` 
) 

ORDER BY `Last_Name` ASC 
LIMIT 30 

Điều đó có thể nhanh hơn một chút so với tham gia trái (tất nhiên, tùy thuộc vào các chỉ số, số lượng bảng của bạn, vv) và gần như chắc chắn là nhiều hơn nhanh hơn sử dụng IN.

+0

Cảm ơn vì điều đó - chắc chắn nhanh hơn cho tôi. – spidie

15
+2

Kết luận của bài viết này: "Đó là lý do tại sao cách tốt nhất để tìm kiếm các giá trị bị thiếu trong MySQL là sử dụng LEFT JOIN/IS NULL hoặc NOT IN chứ không phải là NOT EXISTS." – marcovtwout

+3

liên kết chỉ trả lời = xấu – Andrew

+0

Mặc dù không có liên quan, nhưng một khuôn khổ Để sự tăng cấp của tôi (Laravel) tạo ra truy vấn không tồn tại khi thực hiện khi không có truy vấn – Tebe

1

Có ba cách để thực hiện điều đó.

  1. Lựa chọn
 
     SELECT lt.* FROM table_left l 
     LEFT JOIN 
      table_right r 
     ON  rt.value = lt.value 
     WHERE rt.value IS NULL 
  1. Lựa chọn
 
     SELECT lt.* FROM table_left l 
     WHERE lt.value NOT IN 
     (
     SELECT value 
     FROM table_right r 
     ) 
  1. Lựa chọn
 
     SELECT lt.* FROM table_left l 
     WHERE NOT EXISTS 
     (
     SELECT NULL 
     FROM table_right r 
     WHERE rt.value = lt.value 
     ) 
Các vấn đề liên quan