จะยกเว้นแถวที่ไม่รวมกับตารางอื่นได้อย่างไร


87

ฉันมีสองตารางหนึ่งมีคีย์หลักอื่น ๆ มีเป็นคีย์ต่างประเทศ

ฉันต้องการดึงข้อมูลจากตารางหลักเฉพาะในกรณีที่ตารางรองไม่มีรายการที่มีคีย์ จัดเรียงตรงข้ามกับการรวมภายในแบบธรรมดาซึ่งส่งคืนเฉพาะแถวที่รวมเข้าด้วยกันด้วยคีย์

คำตอบ:


274

ข้อความแสดงแทน

SELECT <select_list> 
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
WHERE B.Key IS NULL

ภาพเต็มของการเข้าร่วม ข้อความแสดงแทน

จาก aticle: http://www.codeproject.com/KB/database/Visual_SQL_Joins.aspx


9
ในที่สุด! ทำไมไม่มีในหนังสือเรียนแล้วทำไมอาจารย์ของฉันที่มหาวิทยาลัยถึงไม่มีสิ่งเหล่านี้! พวกเขาใช้คำอธิบายที่เลวร้ายที่สุดในโลกไม่ใช่จากระยะไกล!
pythonian29033

5
นี่คือทองคำ ฉันเกลียดที่จะเขียนความคิดเห็นที่ไม่มีเนื้อหา แต่ได้รับคำชมอย่างล้นหลาม แต่มาเถอะ! นี่คือคำตอบที่ยอดเยี่ยม ขอบคุณ @Pranay Rana.
0xbe5077ed

1
ช่วยอธิบายหน่อยทำไมB.Key IS NULLแต่เรายังเทียบเคียงA.Key = B.Key?
Do Nhu Vy

1
@DoNhuVy อย่างง่ายการเปรียบเทียบอยู่ในส่วนคำสั่ง "ON" ในการรวมซ้ายหรือขวาหากไม่มีแถวที่ตรงกันจากนั้นแถวที่มี NULL ทั้งหมดจะถูกรวมเข้าด้วยกันหลังจากนั้นคุณทดสอบ IS NULL เพื่อให้ทราบว่าไม่มีแถวที่ตรงกัน . (นี้จะทำงานเฉพาะโดยวิธีการที่ถ้าเขตข้อมูลที่คุณกำลังทดสอบคือไม่เป็นโมฆะคือไม่สามารถมีโมฆะด้วยเหตุผลอื่น ๆ บาง)
เกร็กกอรี่มการ์ ชาค

ฉันใช้แบบสอบถามด้านล่าง: SELECT A * FROM #PurgeFilesListNew A FULL OUTER JOIN #DoNotPurgeFilesListNew B ON A.JobFileId = B.JobFileId AND A.AccountID = B.AccountID WHERE A. JobFileId IS NULL OR B.JobFileId IS NULL A.AccountID IS NULL หรือ B.AccountID IS NULL โดยทั่วไปฉันมีสองค่าที่เปรียบเทียบค่าสองค่าในอนุประโยค "ON" ใช้งานได้ดี แต่แบบสอบถามกำลังส่งคืนแถวว่างสำหรับแถวที่ไม่ตรงกัน วิธีแก้ปัญหานี้? โปรดช่วย
HarshSharma

10
SELECT
   *
FROM
   primarytable P
WHERE
   NOT EXISTS (SELECT * FROM secondarytable S
     WHERE
         P.PKCol = S.FKCol)

โดยทั่วไปแล้ว(NOT) EXISTSเป็นทางเลือกที่ดีกว่า(NOT) INหรือ(LEFT) JOIN


เขาไม่ได้โพสต์ว่า DBRMS ใช้อะไร แต่ใน MySql มีLEFT JOINประสิทธิภาพสูงกว่าNOT EXIST
The Scrum Meister

@ The Scrum Meister: ฉันพูดเร็วกว่านี้ไหม? ค้นหา IN vs EXISTS vs JOIN เพื่อค้นหาความแตกต่างทางความหมายและตรรกะ ...
gbn

@gbn ขออภัยฉันคิดโดย "ทางเลือกที่ดีกว่า" คุณหมายถึงเร็วกว่า ช่วยอธิบายด้วยวิธีใดเป็นทางเลือกที่ดีกว่า descriptionextended.com/2009/09/18/…
The Scrum Meister

1
@ The Scrum Meister: โดยทั่วไปการเข้าร่วมทุกประเภทอาจต้องมีความแตกต่าง ไม่อยู่ในค่าว่างในรายการให้เป็นเท็จ IN / EXISTS มีพฤติกรรมเหมือนกัน อย่างไรก็ตามโครงสร้างที่ "ปลอดภัย" เพียงอย่างเดียวคือ (NOT) EXISTS เว้นแต่คุณจะชอบความไม่สอดคล้อง
gbn


4

ใช้การเข้าร่วมที่เหลือ "ไม่มีอยู่":

SELECT p.*
FROM primary_table p LEFT JOIN second s ON p.ID = s.ID
WHERE s.ID IS NULL


3
SELECT P.*
FROM primary_table P
LEFT JOIN secondary_table S on P.id = S.p_id
WHERE S.p_id IS NULL

2
มีคำถาม .. ถ้าเราใช้เงื่อนไขP.key = S.keyแล้วบอกว่าwhere S.key IS NULLไม่ทำให้ P.key เป็นโมฆะเช่นกัน?
สมจิตร

2

หากคุณต้องการเลือกคอลัมน์จากตารางแรก "ซึ่งมีอยู่ในตารางที่สองเช่นกันในกรณีนี้คุณสามารถใช้ได้เช่นEXCEPTกันในกรณีนี้ชื่อคอลัมน์อาจแตกต่างกันได้เช่นกัน แต่ประเภทข้อมูลควรเหมือนกัน

ตัวอย่าง:

select ID, FName
from FirstTable
EXCEPT
select ID, SName
from SecondTable

0

สิ่งนี้มีประโยชน์ในการใช้ใน COGNOS เนื่องจากอนุญาตให้สร้างคำสั่ง SQL "ไม่อยู่ใน" ใน Cognos ได้ แต่ใช้เวลาในการรันนานเกินไป ฉันได้เข้ารหัสตาราง A ด้วยตนเองเพื่อเข้าร่วมกับตาราง B ใน Cognos เป็น A.key "not in" B.key แต่แบบสอบถามใช้เวลานานเกินไป / ไม่ส่งคืนผลลัพธ์หลังจาก 5 นาที

สำหรับใครก็ตามที่กำลังมองหาโซลูชัน "NOT IN" ใน Cognos นี่คือสิ่งที่ฉันทำ สร้างแบบสอบถามที่รวมตาราง A และ B ด้วย LEFT JOIN ใน Cognos โดยการเลือกประเภทลิงก์: ตาราง A.Key มีค่า "0 ถึง N" ในตาราง B จากนั้นเพิ่มตัวกรอง (ซึ่งสอดคล้องกับ Where Clauses) สำหรับ: ตาราง B .Key เป็นโมฆะ

วิ่งเร็วและเหมือนมีเสน่ห์

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