2012-02-02 16 views
21

मैं बस छोड़कर और MSDN लाइब्रेरी में INTERSECT बारे में पढ़ने और INTERSECT कैसे उपयोग करने के लिए की इस उदाहरण में आए किया गया था:टी-एसक्यूएल में EXCEPT क्यों मौजूद है?

USE AdventureWorks2008R2 GO 
SELECT ProductID 
FROM Production.Product 
INTERSECT 
SELECT ProductID 
FROM Production.WorkOrder ; 
--Result: 238 Rows (products that have work orders) 

शायद मैं पुराने जमाने हूँ, लेकिन मैं आम तौर पर प्राप्त करने के लिए निम्न कोड का प्रयोग करेंगे एक ही परिणाम:

SELECT P.ProductID 
FROM Production.Product P 
INNER JOIN Production.WorkOrder W ON W.ProductID = P.ProductID 

क्या मुझे कुछ याद आ रहा है, या इंटर्न जॉइन के समान ही है? क्या दूसरे पर एक का उपयोग करने के लिए एक प्रदर्शन लाभ है?

EXCEPT के लिए एक ही सवाल। यह कैसे है:

इस से
USE AdventureWorks2008R2; 
GO 
SELECT ProductID 
FROM Production.Product 
EXCEPT 
SELECT ProductID 
FROM Production.WorkOrder ; 
--Result: 266 Rows (products without work orders) 

अलग:

SELECT P.ProductID 
FROM Production.Product P 
LEFT JOIN Production.WorkOrder W ON W.ProductID = P.ProductID 
WHERE W.ProductID IS NULL 

?

+2

-1 का वर्णन करने के लिए अतिरिक्त कॉलम जोड़ा गया: यह नहीं है कि इंटरसेक्ट कैसे काम करता है। आपका पहला उदाहरण उन उत्पादों को वापस नहीं करता है जिनमें कार्य आदेश हैं; यह किसी भी उत्पाद की आईडी लौटाता है जिसमें एक ही आईडी है जो किसी उत्पाद के लिए कार्य आदेश की आईडी के रूप में होती है। –

उत्तर

22

मैं EXCEPT पर ध्यान केंद्रित करने जा रहा हूं क्योंकि मैं इससे अधिक परिचित हूं। साथ ही, एक अस्वीकरण के रूप में, मेरे उदाहरण स्क्लाइट में होंगे, क्योंकि मैं एक लिनक्स बॉक्स पर हूं। हालांकि, स्क्लाइट और एसक्यूएल सर्वर दोनों को कार्यक्षमता का समर्थन करना चाहिए।

INTERSECT और EXCEPTrelational algebra में अंतर्निहित विचारों से उत्पन्न ऑपरेटरों को सेट कर रहे हैं। वे ऑपरेटरों के रूप में विशिष्ट मान पर काम करते हैं।

आपका उदाहरण सरल है। मैं Northwind नमूना डेटाबेस के SQLite संस्करण का उपयोग करके एक counterexample दे दूंगा।

मान लीजिए कि आप उन सभी ग्राहकों के ग्राहक आईडी प्राप्त करना चाहते हैं जिन्होंने 5 के कर्मचारी के साथ आदेश दिया है, लेकिन उन लोगों ने नहीं जिन्होंने 6 के कर्मचारी के साथ आदेश भी दिया है। यह EXCEPT के साथ सरल और प्राकृतिक है।

SELECT CustomerID FROM orders 
WHERE EmployeeID = 5 
EXCEPT 
SELECT CustomerID FROM orders 
WHERE EmployeeID = 6 

यह नॉर्थविंड के मेरे संस्करण पर 14 पंक्तियां देता है।

मान लीजिए कि आप JOIN एस का उपयोग करके इसे फिर से लिखने का निर्णय लेते हैं। शायद ऐसा कुछ?

SELECT o1.CustomerID 
FROM orders o1 INNER JOIN orders o2 ON o1.CustomerID = o2.CustomerID 
WHERE o1.EmployeeID = 5 AND o2.EmployeeID != 6 

हूप्स, 525 पंक्तियां। शायद DISTINCT जोड़ें?

SELECT DISTINCT o1.CustomerID 
FROM orders o1 INNER JOIN orders o2 ON o1.CustomerID = o2.CustomerID 
WHERE o1.EmployeeID = 5 AND o2.EmployeeID != 6 

अब यह 28 पंक्तियाँ, अभी भी बहुत कुछ है कि हम क्या EXCEPT साथ मिल रहे थे की तुलना में अधिक है।इसका कारण यह है कि यह ग्राहक आईडी को नहीं हटा रहा है जिसने 6 के साथ ऑर्डर दिया है। बल्कि, यह सभी ग्राहक आईडी हैं जिनके पास 5 और के साथ ऑर्डर है 6 से अधिक कर्मचारी, चाहे उनके पास ऑर्डर हो या नहीं कर्मचारी आईडी 6.

संक्षेप में, EXCEPT और INTERSECT ऑपरेटर सेट हैं जो दो प्रश्नों की तुलना करते हैं, अद्वितीय tuples लौटते हैं, और निश्चित रूप से उनका उपयोग होता है।

+3

आप से इस चयन o1.CustomerId की तरह कोड लिख सकते हैं (आदेश से चयन ग्राहक आईडी जहां EmployeeID = 5 ) O1 बाईं बाहरी के रूप में शामिल ( आदेश से CustomerID का चयन करें जहां EmployeeID = 6 ) O1 पर o2 के रूप में। ग्राहक आईडी = o2.CustomerID जहां o2.CustomerID शून्य है – danmiao

0

मेरी राय EXCEPT और INTERSECT में शामिल होने के आदेश के रूप में ही काम करने के लिए उपयोग किया जाता है, लेकिन यह टेबल के साथ सरल प्राथमिक कुंजी नहीं है, उदाहरण के लिए:

INTERSECT साथ:

SELECT FIRSTNAME, 
     LASTNAME, 
     ADDRESSLINE1, 
     CITY, 
     STATEPROVINCECODE, 
     POSTALCODE 
FROM MANAGER 
EXCEPT 
SELECT FIRSTNAME, 
     LASTNAME, 
     ADDRESSLINE1, 
     CITY, 
     STATEPROVINCECODE, 
     POSTALCODE 
FROM CUSTOMER 

और शामिल होने के साथ ही परिणाम है, आप क्या करना चाहिए:

SELECT M.FIRSTNAME, 
     M.LASTNAME, 
     M.ADDRESSLINE1, 
     M.CITY, 
     M.STATEPROVINCECODE, 
     M.POSTALCODE 
FROM  MANAGER M 
WHERE NOT EXISTS (SELECT * 
        FROM CUSTOMER C 
        WHERE M.FIRSTNAME = C.FIRSTNAME 
          AND M.LASTNAME = C.LASTNAME 
          AND M.ADDRESSLINE1 = C.ADDRESSLINE1 
          AND M.CITY = C.CITY 
          AND M.POSTALCODE = C.POSTALCODE) 
GROUP BY M.FIRSTNAME,M.LASTNAME,M.ADDRESSLINE1,M.CITY, 
     M.STATEPROVINCECODE,M.POSTALCODE 

अधिक जानकारी here

1

अपने "बराबर" प्रश्नों के अपने उदाहरण गलत कर रहे हैं - INTERSECT साथ क्वेरी हमेशा INNER JOIN और EXCEPT और LEFT JOIN के लिए एक ही रूप में एक ही परिणाम वापस नहीं। INTERSECT के बारे में विशिष्ट उदाहरण में

देखो:

DECLARE @t TABLE(t INT NOT NULL) 
DECLARE @x TABLE(x INT NOT NULL) 

INSERT @t 
VALUES (1), (2), (3) 

INSERT @x VALUES(1), (1), (1) 

SELECT t FROM @t 
INTERSECT SELECT x FROM @x 

SELECT t FROM @t 
INNER JOIN @x ON x = t 

INTERSECT अधिक की तरह है (नहीं बल्कि एक ही) के रूप में IN खंड:

SELECT t FROM @t 
WHERE t IN (select x FROM @x) 

या के रूप में EXISTS

SELECT t FROM @t 
WHERE EXISTS (select * FROM @x WHERE x = t) 

वही उदाहरण जिन्हें आप EXCEPT खंड में अनुकूलित कर सकते हैं।

+0

आप सही हैं, लेकिन इसके पीछे सिद्धांत के लिए मेरा उत्तर देखें ... – gbn

19
  • दूसरे को काटना और छोड़कर कर रहे हैं अर्द्ध मिलती
  • शामिल हों

सम में शामिल होने तो जब आप 2 टेबल से मेल खाने वाले, कहते हैं, 5 पंक्तियों और 3 पंक्तियों

  • में शामिल होने है जॉइन 15 पंक्तियां देता है
  • इंटरसेक्ट 3 पंक्तियां देता है

छोड़कर बाहरी के समान है, इसी कारण

के लिए शामिल हों हम के बारे में अर्द्ध मिलती है पर हैं तो ज्यादातर

  • INTERSECT मौजूद
  • के रूप में छोड़कर देता है एक ही परिणाम देता है एक ही परिणाम के रूप में मौजूद नहीं है

"ज्यादातर" आता है, क्योंकि दोनों को काटना और

01 को छोड़कर
  • इलाज शून्य अलग ढंग से: फरवरी 2013: एक पूरी तरह से काम किया है उदाहरण के लिए, this by Paul White aka SQL Kiwi
  • लागू DISTINCT

संपादित करें, की यह सब

DECLARE @t1 TABLE (t1col INT); 
INSERT @t1 VALUES (1), (2), (2), (3), (3), (5), (5); 

DECLARE @t2 TABLE (t2col INT); 
INSERT @t2 VALUES (1), (2), (3), (4); 

SELECT 'INNER JOIN', * FROM @t1 t1 JOIN @t2 t2 ON t1.t1col = t2.t2col -- same both ways 

SELECT 't1 INTERSECT t2', * FROM @t1 INTERSECT SELECT 't1 INTERSECT t2', * FROM @t2; 

SELECT 't2 INTERSECT t1', * FROM @t2 INTERSECT SELECT 't2 INTERSECT t1', * FROM @t1; 

SELECT 't1 EXISTS t2', * FROM @t1 t1 
WHERE EXISTS (SELECT * FROM @t2 t2 WHERE t1.t1col = t2.t2col); 

SELECT 't2 EXISTS t1', * FROM @t2 t2 
WHERE EXISTS (SELECT * FROM @t1 t1 WHERE t1.t1col = t2.t2col); 

SELECT 't1 LEFT JOIN t2, IS NULL', * FROM @t1 t1 LEFT JOIN @t2 t2 ON t1.t1col = t2.t2col WHERE t2.t2col IS NULL 
SELECT 't2 LEFT JOIN t1, IS NULL', * FROM @t2 t2 LEFT JOIN @t1 t1 ON t1.t1col = t2.t2col WHERE t1.t1col IS NULL 

SELECT 't1 EXCEPT t2', * FROM @t1 EXCEPT SELECT 't1 EXCEPT t2', * FROM @t2; 

SELECT 't2 EXCEPT t1', * FROM @t2 EXCEPT SELECT 't2 EXCEPT t1', * FROM @t1; 

SELECT 't1 NOT EXISTS t2', * FROM @t1 t1 
WHERE NOT EXISTS (SELECT * FROM @t2 t2 WHERE t1.t1col = t2.t2col); 

SELECT 't2 NOT EXISTS t1', * FROM @t2 t2 
WHERE NOT EXISTS (SELECT * FROM @t1 t1 WHERE t1.t1col = t2.t2col); 

अद्यतन त्वरित डेमो देखें।ऑपरेशन

+0

+1 व्यापक! –

+1

@ माइकल एरिक्सन: मैं गलत हूं, तय हूं। – gbn

+0

से पहले मेरे पास पर्याप्त पर्याप्त डेमो स्क्रिप्ट नहीं थी, असल में, वापस देखकर, एक 'एंटीजॉइन]' नहीं है (http://en.wikipedia.org/wiki/Relational_algebra#Joins_and_join-like_operators), सेमिजॉइन नहीं ? – voithos

संबंधित मुद्दे