การดำเนินการแตกต่างสมมาตรใน Transact-SQL?


10

ฉันได้รู้จักกันเสมอเกี่ยวกับUNIONผู้ประกอบการใน SQL แต่เมื่อเร็ว ๆ นี้พบว่ามีผู้ประกอบการชุดอื่น ๆและINTERSECT EXCEPTฉันไม่สามารถค้นหาผู้ดำเนินการที่ดำเนินการชุดใหญ่ชุดที่สี่ความแตกต่างแบบสมมาตร (เช่นตรงข้ามกับINTERSECT)

ดูเหมือนว่าฉันจะได้รับผลลัพธ์ที่ต้องการโดยใช้สิ่งที่ชอบ

SELECT Field FROM A UNION SELECT Field FROM B 
EXCEPT
SELECT Field FROM A INTERSECT SELECT Field FROM B

(สมมติว่าฉันมีสิทธิ์เหนือกว่า) หรือด้วยการเข้าร่วมต่อต้านแบบเต็ม:

SELECT A.Field, B.Field
FROM A
FULL JOIN B ON B.Id = A.Id
WHERE B.Id IS NULL OR A.Id IS NULL

แต่ทั้งคู่ดูเหมือนว่าข้อความค้นหาค่อนข้างเข้มงวดโดยเฉพาะอย่างยิ่งเมื่อเปรียบเทียบกับการดำเนินการพื้นฐานสามชุดอื่น ๆ มีการดำเนินการความแตกต่างแบบสมมาตรใน SQL และฉันไม่พบมันในเอกสารประกอบ? หรือมีวิธี "มาตรฐาน" ที่จะใช้ใน T-SQL?


2
(a EXCEPT b) UNION ALL (b EXCEPT a);อาจมีประสิทธิภาพมากขึ้น
ypercubeᵀᴹ

@ypercube ที่มี 3 การรวมหรือการดำเนินการคล้ายการเข้าร่วม ฉันไม่สามารถนึกถึงเหตุผลใด ๆ ที่อาจมีประสิทธิภาพมากกว่าการเข้าร่วมเต็มรูปแบบ
usr

@usr เป็นจริงการดำเนินการเข้าร่วม 2 เหมือนไม่ใช่ 3 ยูเนี่ยนทั้งหมดเป็นการดำเนินการที่มีค่าใช้จ่ายน้อยกว่ามาก ฉันยอมรับว่าFULL JOINอาจมีประสิทธิภาพมากกว่า การทดสอบสามารถเปิดเผยสิ่งที่ดีที่สุด และแน่นอนถ้าต้องการคอลัมน์เพิ่มเติม / ต่างจากแต่ละตารางโซลูชันของฉันไม่สามารถขยายได้อย่างง่ายดาย
ypercubeᵀᴹ

คำตอบ:


3

ผู้ประกอบการชุดทั้งหมดมีการแปลเพื่อเข้าร่วมหรือผู้ประกอบการเหมือนเข้าร่วม คุณสามารถเห็นได้ว่าในแผนแบบสอบถาม

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


ที่ทำให้ความรู้สึก แต่เหตุผลที่ผมชอบที่จะใช้ประกอบชุดเป็นเพราะพวกเขาไม่ได้สร้าง "คอลัมน์พิเศษ" ... ฉันสามารถทำสิ่งที่ชอบและได้รับรายการเดียวของSELECT Id FROM A WHERE <stuff> EXCEPT Select Id FROM A WHERE <other stuff> Idฉันไม่สามารถหาวิธีที่จะทำได้ด้วยการเข้าร่วมเต็มรูปแบบ ... ฉันต้องจัดการกับการมีIdคอลัมน์สองชุดแล้วรวมเข้าด้วยกันหรือไม่
KutuluMike

คุณสามารถพูดISNULL(a.Col, b.Col) AS Colได้ ล้อมที่ในตารางที่ได้รับหรือ CTE และคุณสามารถใช้ชุดผลลัพธ์ "พับ" สำหรับการดำเนินการเพิ่มเติม (Btw ฉันยอมรับตัวดำเนินการความแตกต่างแบบสมมาตรควรมีอยู่)
usr

2
@MichaelEdenfield ในทางกลับกันถ้าคุณต้องการคอลัมน์อื่น ๆ ที่ไม่ได้ใช้ในการเปรียบเทียบ / ต่างกัน คุณสามารถทำได้ด้วยการเข้าร่วม แต่ไม่ใช่กับการตัดกัน / ยกเว้น ดังนั้นฉันจึงเห็นได้ว่าในบางกรณีการเปลี่ยนแปลงที่เกิดขึ้นจริงนั้นซับซ้อนมากขึ้นในระยะยาว
Aaron Bertrand

2

ฉันคิดว่านี่เป็นทางออกที่ดีงาม มันใช้สหภาพทั้งหมดระหว่างสองเลือกด้วยแบบสอบถามย่อยไม่ได้อยู่ ดีกว่าการรวมยูเนี่ยนและยกเว้นเพราะคุณสามารถรวมฟิลด์ที่ไม่ตรงกับเส้นโครง

SELECT  'A' TableName, FileType FROM KFX_Inventory I 
    WHERE Not Exists (Select Top 1 1 from KFX_FileType FT WHERE FT.FileType = I.FileType)
UNION ALL
SELECT  'B', FileType FROM KFX_FILEType FT 
    WHERE Not Exists (Select Top 1 1 from KFX_Inventory I WHERE FT.FileType = I.FileType)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.