Mysql: Chọn các hàng từ một bảng không nằm trong bảng khác


118

Làm thế nào để chọn tất cả các hàng trong một bảng mà không xuất hiện trên bảng khác?

Bảng 1:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Ban 2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Tia       | Carrera  | 1975-09-18 |
| Nikki     | Taylor   | 1972-03-04 |
+-----------+----------+------------+

Ví dụ đầu ra cho các hàng trong Bảng1 không có trong Bảng2:

+-----------+----------+------------+
| FirstName | LastName | BirthDate  |
+-----------+----------+------------+
| Yamila    | Diaz     | 1972-03-04 |
+-----------+----------+------------+

Có lẽ một cái gì đó như thế này sẽ hoạt động:

SELECT * FROM Table1 WHERE * NOT IN (SELECT * FROM Table2)

Câu trả lời:


96

Nếu bạn có 300 cột như đã đề cập trong một nhận xét khác và bạn muốn so sánh trên tất cả các cột (giả sử các cột đều có cùng tên), bạn có thể sử dụng a NATURAL LEFT JOINđể kết hợp ngầm trên tất cả các tên cột phù hợp giữa hai bảng để bạn không cần phải gõ thủ công tất cả các điều kiện tham gia:

SELECT            a.*
FROM              tbl_1 a
NATURAL LEFT JOIN tbl_2 b
WHERE             b.FirstName IS NULL

Lưu ý rằng điều này chỉ hoạt động như mong đợi khi không có cột nào có giá trị NULL. Trong MySQL NULL! = NULL nên mọi hàng có giá trị NULL sẽ được trả về ngay cả khi có một hàng trùng lặp trong bảng thứ hai.
Kyle Kochis

84
Nếu bạn có 300 cột, bạn nên thiết kế lại cơ sở dữ liệu của mình.
Iharob Al Asimi

Này, điều này cũng làm việc cho tôi, cảm ơn! nhưng đó sẽ là một vấn đề nếu các hàng> 300 như bạn đã đề cập ở trên?
thekucays,

Tôi vẫn còn nhầm lẫn về truy vấn btw..nếu tôi thay đổi "where b.FirstName là null" thành "where b.LastName là null" chẳng hạn? có gì khác biệt? Tôi xin lỗi vì yêu cầu này, tôi vẫn còn mới để sql: D
thekucays

184

Bạn cần thực hiện chọn con dựa trên tên cột, không phải *.

Ví dụ: nếu bạn có một idtrường chung cho cả hai bảng, bạn có thể làm:

SELECT * FROM Table1 WHERE id NOT IN (SELECT id FROM Table2)

Tham khảo cú pháp truy vấn con MySQL để biết thêm ví dụ.


1
Cảm ơn bạn đã làm rõ! nhưng tôi thực sự không cần phải căn cứ việc lựa chọn hàng trên lĩnh vực nào, vì tôi đang quan tâm đến bất kỳ biến thể của bất kỳ lĩnh vực ở hàng ...

Nếu chỉ có một vài cột để so sánh, bạn có thể thực hiện phép nối theo ví dụ của @ Steve. Nếu bạn thực sự đang yêu cầu so sánh tổng thể dữ liệu trong hai bảng với nhiều cột, bạn có thể muốn tìm kiếm một công cụ khác biệt của MySQL .
Stennie

2
Lưu ý rằng điều này sẽ luôn trả về một tập hợp trống nếu cột bạn đang xem trong Table2 chứa rỗng. Không phải là vấn đề nếu bạn đang làm việc đó dựa trên khóa chính, nhưng có liên quan đến những người đang cố gắng sử dụng truy vấn này trong các ngữ cảnh khác.
Mark Amery,

4
Nhưng nếu chúng ta đang nói về dữ liệu lớn thì sao? Và Table2 chứa 100M hàng chẳng hạn?
frops

Câu trả lời thông minh và thông minh. Cảm ơn người bạn đời
Anjana Silva

44
SELECT *
FROM Table1 AS a
WHERE NOT EXISTS (
  SELECT *
  FROM Table2 AS b 
  WHERE a.FirstName=b.FirstName AND a.LastName=b.Last_Name
)

EXISTS sẽ giúp bạn...


2
Câu trả lời tốt, tiết kiệm cho các tập dữ liệu lớn, cảm ơn.
ekerner

Mạnh. Câu trả lời tốt nhất cho các tập dữ liệu lớn
Ian Chadwick

35

Một LEFT JOIN tiêu chuẩn có thể giải quyết sự cố và nếu các trường trên phép nối được lập chỉ mục,
cũng sẽ nhanh hơn

SELECT *
FROM Table1 as t1 LEFT JOIN Table2 as t2 
ON t1.FirstName = t2.FirstName AND t1.LastName=t2.LastName
WHERE t2.BirthDate Is Null

được rồi, tôi đoán đó phải là nó, btw tại sao WHERE t2.Birthdate Is Nullthay vì AND t1.Birthdate = t2.Birthdate?

Bởi vì nếu bạn thêm rằng, sau đó mỗi hàng sẽ được trả lại, bạn nói rằng trong đầu ra nên chỉ xuất hiện hàng không có trong bảng thứ hai
Steve

1
Đây là một câu trả lời tuyệt vời, vì nó không yêu cầu trả lại tất cả các hàng của Table2!
dotancohen

Tôi đồng ý, câu trả lời tuyệt vời. Tôi có một bảng man-nhiều giữa 4 bảng, đặt AND vào phần nối bên trong chắc chắn sẽ tiết kiệm hơn.
DR.

6

Thử:

SELECT * FROM table1
    LEFT OUTER JOIN table2
    ON table1.FirstName = table2.FirstName and table1.LastName=table2.LastName
    WHERE table2.BirthDate IS NULL

4

Hãy thử truy vấn đơn giản này. Nó hoạt động hoàn hảo.

select * from Table1 where (FirstName,LastName,BirthDate) not in (select * from Table2);

-3

Điều này đã làm việc cho tôi trong Oracle:

SELECT a.* 
    FROM tbl1 a 
MINUS 
SELECT b.* 
    FROM tbl2 b;

Câu hỏi là về MySQL.
jelder

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.