ลบแถว sql ที่ ID ไม่มีการจับคู่จากตารางอื่น


160

ฉันกำลังพยายามลบรายการเด็กกำพร้าในตาราง MySQL

ฉันมี 2 ตารางเช่นนี้

ตารางfiles:

| id | ....
------------
| 1  | ....
| 2  | ....
| 7  | ....
| 9  | ....

ตารางblob:

| fileid | ....
------------
| 1  | ....
| 2  | ....
| 3  | ....
| 4  | ....
| 4  | ....
| 4  | ....
| 9  | ....

fileidและidคอลัมน์สามารถใช้ในการเข้าร่วมโต๊ะด้วยกัน

ฉันต้องการที่จะลบแถวทั้งหมดในตารางblobที่ไม่สามารถพบได้ในตารางfileidfiles.id

ดังนั้นใช้ตัวอย่างด้านบนที่จะลบแถว: 3 & 4 (s) ในblobตาราง


1
ข้ามไปที่คำตอบที่สองถ้าคุณกำลังใช้nulls
Pacerier

คำตอบ:


327

ใช้ซ้ายเข้าร่วม / เป็นโมฆะ:

DELETE b FROM BLOB b 
  LEFT JOIN FILES f ON f.id = b.fileid 
      WHERE f.id IS NULL

ใช้ไม่อยู่:

DELETE FROM BLOB 
 WHERE NOT EXISTS(SELECT NULL
                    FROM FILES f
                   WHERE f.id = fileid)

ใช้ไม่ได้อยู่ใน:

DELETE FROM BLOB
 WHERE fileid NOT IN (SELECT f.id 
                        FROM FILES f)

คำเตือน

เมื่อใดก็ตามที่เป็นไปได้ให้ดำเนินการลบภายในธุรกรรม (สมมติว่ารองรับ - IE: ไม่ใช่ที่ MyISAM) เพื่อให้คุณสามารถใช้การย้อนกลับเพื่อย้อนกลับการเปลี่ยนแปลงในกรณีที่เกิดปัญหา


12
ซึ่งโดยทั่วไปแล้วเร็วที่สุดของข้างต้นคืออะไร?
Hampus Brynolf

2
ด้วยเหตุผลบางอย่างการลบโดยใช้ LEFT JOIN ไม่ทำงานบน MS SQL Server Mgmt Studio (ไม่แน่ใจว่าทำไมเพราะมันเพิ่งบ่นเกี่ยวกับ LEFT JOIN) ใครรู้ว่าทำไมเป็นอย่างนั้น? มันใช้งานได้โดยไม่มีอยู่จริง :)
แอนนา

5
FYI นี่คือการอภิปรายที่มีประโยชน์ของประสิทธิภาพความสัมพันธ์ของทั้งสามวิธี: explainextended.com/2009/09/18/...
Moustachio

2
@Pacerier - "ผิด" เป็นบิตที่แข็งแกร่ง เพื่อให้แน่ใจว่าผู้คนเข้าใจคำตอบทำงานถ้าfileidเป็นที่ไม่ใช่ nullable นอกจากนี้โซลูชันที่สาม ( NOT IN) ต้องการเพียงว่าf.idไม่สามารถลบล้างได้ สันนิษฐานว่าเป็นคีย์หลักดังนั้นมันจะเป็น
ToolmakerSteve

2
สำหรับคนที่พยายามใช้ w / SQLite นี้
bunkerdive

26
DELETE FROM blob 
WHERE fileid NOT IN 
       (SELECT id 
        FROM files 
        WHERE id is NOT NULL/*This line is unlikely to be needed 
                               but using NOT IN...*/
      )

คืออะไร"/ * บรรทัดนี้ไม่น่าจะมีความจำเป็น แต่ใช้ไม่ได้ใน ... * /"ควรจะหมายถึงอะไร?
Pacerier

1
@Pacerier - NOT IN (NULL)ส่งคืนชุดผลลัพธ์ว่างดังนั้นจำเป็นต้องมี NULLs แต่idคอลัมน์อาจจะไม่เป็นโมฆะดังนั้นจึง "ไม่จำเป็นต้องมี"
Martin Smith

ว้าวจับได้ดี ดังนั้นคำตอบของ omgponies จึงผิด! not in(null)มันค่อนข้างสมเหตุสมผล, ทำไมมันไม่ทำงาน? เหตุผลเบื้องหลังคืออะไร
Pacerier


1
@bunkerdive จากนั้นใช้ชื่อวัตถุสามส่วนที่มีชื่อฐานข้อมูล
Martin Smith

17
DELETE FROM blob
WHERE NOT EXISTS (
    SELECT *
    FROM files
    WHERE id=blob.id
)

1
ผมคิดว่ามีความเป็นไปและfiles.id blob.fileidฉันเดาว่าคำค้นหาของคุณจะทำให้เกิดข้อผิดพลาด
jww

-8
delete from table1 t1 
    WHERE not exists (select id from table2 where related_field_in_t2=t1.id) 
    AND not exists (select id from table3 where related_field_in_t3=t1.id) 
    AND not exists (select id from table4 where related_field_t4=t1.id) 
    AND not exists (select id from table5 where related_field_t5=t1.id);

3
ฉันลงคะแนนเพราะ: 1. นี่ไม่ได้พยายามตอบคำถามในบริบทที่โพสต์ 2. ไม่มีคำอธิบาย (และคำตอบที่ใช้รหัสอย่างเดียวคือราคาต่ำใน Stackoverflow) 3. NOT EXISTSโพสต์แล้วเมื่อ 9 ปีที่แล้ว 4. คุณยังไม่ได้ส่งเสริมวิธีปฏิบัติที่ดีที่สุดในการใช้คำหลักแบบ all-for สำหรับ MySQL อย่างสม่ำเสมอ พูดอีกอย่างก็คือไม่มีอะไรคุ้มค่าที่จะรักษานี่คือเหตุผลที่ฉันลงคะแนนให้ลบโพสต์นี้ด้วย
mickmackusa
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.