Mysql: เลือกแถวจากตารางที่ไม่ได้อยู่ในตารางอื่น


118

จะเลือกแถวทั้งหมดในตารางเดียวที่ไม่ปรากฏในอีกตารางได้อย่างไร?

ตารางที่ 1:

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

Table2:

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

ตัวอย่างผลลัพธ์สำหรับแถวใน Table1 ที่ไม่อยู่ใน Table2:

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

บางทีสิ่งนี้ควรใช้งานได้:

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

คำตอบ:


96

หากคุณมี 300 คอลัมน์ตามที่คุณกล่าวถึงในความคิดเห็นอื่นและคุณต้องการเปรียบเทียบกับคอลัมน์ทั้งหมด (สมมติว่าคอลัมน์นั้นเป็นชื่อเดียวกันทั้งหมด) คุณสามารถใช้ a NATURAL LEFT JOINเพื่อรวมชื่อคอลัมน์ที่ตรงกันทั้งหมดระหว่างตารางทั้งสองโดยปริยายเพื่อให้คุณ ไม่ต้องพิมพ์เงื่อนไขการเข้าร่วมทั้งหมดด้วยตนเอง:

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

โปรดทราบว่าสิ่งนี้ใช้ได้ผลตามที่คาดไว้เมื่อไม่มีคอลัมน์ใดที่มีค่า NULL ใน MySQL NULL! = NULL ดังนั้นทุกแถวที่มีค่า NULL จะถูกส่งกลับแม้ว่าจะมีแถวที่ซ้ำกันในตารางที่สองก็ตาม
Kyle Kochis

84
หากคุณมี 300 คอลัมน์คุณควรออกแบบฐานข้อมูลของคุณใหม่
Iharob Al Asimi

เฮ้มันได้ผลสำหรับฉันเช่นกันขอบคุณ! แต่จะเป็นปัญหาหรือไม่ถ้าแถว> 300 เหมือนที่กล่าวไว้ข้างต้น
thekucays

ฉันยังสับสนเกี่ยวกับแบบสอบถาม btw .. จะเกิดอะไรขึ้นถ้าฉันเปลี่ยน "โดยที่ b.FirstName เป็นโมฆะ" เป็น "โดยที่ b.LastName เป็นโมฆะ" อะไรคือความแตกต่าง? ฉันขอโทษที่ถามสิ่งนี้ฉันยังใหม่กับ sql: D
thekucays

184

ที่คุณต้องทำ subselect *ขึ้นอยู่กับชื่อคอลัมน์ไม่

ตัวอย่างเช่นหากคุณมีidเขตข้อมูลร่วมกับทั้งสองตารางคุณสามารถทำได้:

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

อ้างถึงไวยากรณ์การสืบค้นย่อย MySQLสำหรับตัวอย่างเพิ่มเติม


1
ขอขอบคุณสำหรับการชี้แจง! แต่ฉันไม่จำเป็นต้องอิงการเลือกแถวในฟิลด์ใด ๆ เพราะฉันสนใจรูปแบบของฟิลด์ใด ๆ ในแถว ...

หากมีคอลัมน์ให้เปรียบเทียบเพียงไม่กี่คอลัมน์คุณสามารถเข้าร่วมได้ตามตัวอย่างของ @ สตีฟ หากคุณเป็นจริงขอเปรียบเทียบทั่วไปของข้อมูลในสองตารางที่มีหลายคอลัมน์คุณอาจต้องการที่จะมองหาเครื่องมือ MySQL diff
Stennie

2
โปรดทราบว่าสิ่งนี้จะส่งคืนชุดว่างเสมอหากคอลัมน์ที่คุณกำลังดูใน Table2 มี null ไม่ใช่ปัญหาหากคุณทำตามคีย์หลัก แต่เกี่ยวข้องกับผู้ที่พยายามใช้คำค้นหานี้ในบริบทอื่น ๆ
Mark Amery

4
แต่ถ้าเราพูดถึงข้อมูลขนาดใหญ่ล่ะ? และ Table2 มี 100M แถวเช่น?
กบ

คำตอบที่ชาญฉลาดและชาญฉลาด ขอบคุณเพื่อน
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 จะช่วยคุณ...


2
คำตอบที่ดีประหยัดสำหรับชุดข้อมูลขนาดใหญ่ขอบคุณ
ekerner

แข็งแรง คำตอบที่ดีที่สุดสำหรับชุดข้อมูลขนาดใหญ่
Ian Chadwick

35

LEFT JOIN มาตรฐานสามารถแก้ปัญหาได้และหากมีการจัดทำดัชนีเขตข้อมูลในการเข้าร่วมก็
ควรเร็วขึ้นด้วย

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

เอาล่ะฉันเดาว่าต้องเป็นอย่างนั้น btw ทำไมWHERE t2.Birthdate Is Nullแทนที่จะเป็นAND t1.Birthdate = t2.Birthdate?

เพราะถ้าคุณเพิ่มสิ่งนั้นทุกแถวจะถูกส่งกลับคุณบอกว่าในผลลัพธ์ควรปรากฏเฉพาะแถวที่ไม่อยู่ในตารางที่สอง
สตีฟ

1
นี่เป็นคำตอบที่ยอดเยี่ยมเนื่องจากไม่จำเป็นต้องส่งคืนแถวทั้งหมดTable2!
dotancohen

ฉันเห็นด้วยคำตอบที่ดี ฉันมีโต๊ะหลายโต๊ะระหว่าง 4 โต๊ะการใส่ AND ในการรวมด้านในนั้นจะประหยัดกว่า
DR


4

ลองใช้แบบสอบถามง่ายๆนี้ มันทำงานได้อย่างสมบูรณ์

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


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.