2010-09-07 11 views
6

तुलना जब दो सेट दिए गए हैंTSQL दो सेट

एस 1 = {ए, बी, सी, डी} s2 = {बी, सी, डी, एक}

(यानी)

TableA 

Item 
a 
b 
c 
d 

TableB 

Item 
b 
c 
d 
a 

"तालिका ए और टेबलबी में तत्व बराबर हैं" प्रदर्शित करने के लिए एसक्यूएल क्वेरी कैसे लिखें।

आउटपुट [सपा या यूडीएफ का उपयोग किए बिना]

Elements in TableA and TableB contains identical sets 
+0

आप के लिए ** दूसरे को काट नहीं करना चाहते हैं ** उन्हें? –

+0

बीटीडब्ल्यू, यदि आपको सेट * संग्रह * के भीतर मिलान सेट के लिए ** खोज ** की आवश्यकता है, तो यह एक अलग समस्या है, और यहां समाधान बहुत मदद नहीं कर सकते हैं। –

उत्तर

8

उपयोग:

साथ
SELECT CASE 
     WHEN COUNT(*) = (SELECT COUNT(*) FROM a) 
      AND COUNT(*) = (SELECT COUNT(*) FROM b) THEN 'Elements in TableA and TableB contains identical sets' 
     ELSE 'TableA and TableB do NOT contain identical sets' 
     END 
    FROM (SELECT a.col 
      FROM a 
     INTERSECT 
     SELECT b.col 
      FROM b) x 

टेस्ट:

WITH a AS (
    SELECT 'a' AS col 
    UNION ALL 
    SELECT 'b' 
    UNION ALL 
    SELECT 'c' 
    UNION ALL 
    SELECT 'd'), 
    b AS (
    SELECT 'b' AS col 
    UNION ALL 
    SELECT 'c' 
    UNION ALL 
    SELECT 'd' 
    UNION ALL 
    SELECT 'a') 
SELECT CASE 
     WHEN COUNT(*) = (SELECT COUNT(*) FROM a) 
      AND COUNT(*) = (SELECT COUNT(*) FROM b) THEN 'yes' 
     ELSE 'no' 
     END 
    FROM (SELECT a.col 
      FROM a 
     INTERSECT 
     SELECT b.col 
      FROM b) x 
+1

उपट्री लागत पर बहुत ही रोचक जानकारी। –

+0

यह प्रति तालिका + 1 में शामिल 2 पढ़ता है। क्या कोई नहीं जानता कि 'पूर्ण जॉइन' का उपयोग कैसे करें? –

+0

@ पीटर: मैंने आपका पूरा जॉइन विकल्प चलाया है, आपके पूर्ण जॉइन और इंटरसेक्ट या एक्सेप्ट (एसएस2005 पर वैसे भी) का उपयोग करके एक बेहद व्यापक प्रदर्शन मार्जिन है। मुझे लगता है कि इंटरसेक्ट के लिए थोड़ा अधिक लागत (बनाम निक्स का एक्सेप्ट संस्करण) उचित संदेश प्रदर्शित होने के लिए गणना के कारण है। –

3

मेरे monstrocity:

;with SetA as 
(select 'a' c union 
select 'b' union 
select 'c') 
, SetB as 
(select 'b' c union 
select 'c' union 
select 'a' union 
select 'd' 
) 
select case (select count(*) from (
select * from SetA except select * from SetB 
union 
select * from SetB except select * from SetA 
)t) 
when 0 then 'Equal' else 'NotEqual' end 'Equality' 
+0

0.0178567 की उपट्री लागत - सीएमएसजेआर के उत्तर से बेहतर बाल –

+0

मेरा एईपी कहता है कि एसटीसी 0.0112 9 है। लेकिन फिर, मैं पहले से ही उन सेटों को तैयार किए बिना पूरी तरह से क्वेरी चला गया। –

+0

मैं दो पास चलाता हूं, यह जांचने के लिए कि क्वेरी झूठी और सकारात्मक नमूने के लिए वैध आउटपुट लौटा रही है। यदि क्वेरी प्रीलिम परीक्षण पास नहीं करती है तो मैं लागत पोस्ट नहीं करूंगा। –

2

और छोड़कर साथ यह कर सकता है एक मामले

select 
    case 
    when count (1)=0 
     then 'Elements in TableA and TableB contains identical sets' 
    else 'Nope' end from (
     select item from s1 
     EXCEPT 
     select item from s2 
) b 
+0

मुझे यह समाधान पसंद है। :) –

+2

एस 2 में एस 1 की तुलना में अधिक आइटम हो सकते हैं, लेकिन यह क्वेरी दावा करेगी कि वे समान हैं। –

+0

कुछ लोग तर्क देंगे कि सेट अभी भी वही हैं, फिर आप अगर चाहें तो गणना कर सकते हैं, या यदि आप वास्तव में ऊब गए हैं तो आप पंक्ति चेकसम कर सकते हैं। – Nix

3

से सावधान रहें, मैं उपयोग एक क्रॉस के साथ जुड़ें हूँ।

Declare @t1 table(val varchar(20)) 
Declare @t2 table(val varchar(20)) 


insert into @t1 values ('a') 
insert into @t1 values ('b') 
insert into @t1 values ('c') 
insert into @t1 values ('d') 


insert into @t2 values ('c') 
insert into @t2 values ('d') 
insert into @t2 values ('b') 
insert into @t2 values ('a') 

select 
    case when 
    count(1) = 
    (((Select count(1) from @t1) 
    + (Select count(1) from @t2))/2.0) 
    then 1 else 0 end as SetsMatch from 
@t1 t1 cross join @t2 t2 
where t1.val = t2.val 
+0

0.0178713 की उप-लागत लागत - 'INTERSECT' और' EXCEPT' विकल्प अधिक कुशलतापूर्वक प्रदर्शन करते हैं। –

+0

मेरे अंदर एक आंतरिक शामिल होने जैसा दिखता है। –

+0

@cmsjr: [क्रॉस जॉइन SQL सर्वर 2000 पर समर्थित है] (http://msdn.microsoft.com/en-us/library/aa259187%28SQL.80%29.aspx), तो मुझे लगता है कि आप कैसे हैं [ इंटरैक्ट और एक्सेप्ट] (http://msdn.microsoft.com/en-us/library/ms188055.aspx) 2005+ कार्यक्षमता हैं? अपग्रेड =) –

5

इस तरह कुछ है, FULL JOIN का उपयोग कर:

SELECT 
    CASE 
    WHEN EXISTS (
     SELECT * FROM s1 FULL JOIN s2 ON s1.Item = s2.Item 
     WHERE s1.Item IS NULL OR s2.Item IS NULL 
    ) 
    THEN 'Elements in tableA and tableB are not equal' 
    ELSE 'Elements in tableA and tableB are equal' 
    END 

इस के आधार पर है शॉर्ट-सर्किट, पहली गैर मैच पर अन्य समाधान है कि प्रत्येक तालिका के 2 पूर्ण स्कैन की आवश्यकता के विपरीत (एक बार COUNT (*) के लिए, एक बार जॉइन/इंटरसेक्ट के लिए)।

अनुमानित लागत अन्य समाधानों की तुलना में काफी कम है।

+0

मेरा प्रारंभिक दृष्टिकोण। मुझे लगता है कि यह मजेदार नहीं है! :) –

+0

0.0178565 के वास्तविक सबट्री लागत (मेरे लिए) * * डेनिस के उत्तर से मुश्किल से कम, सीएमएसजेआर के उत्तर से थोड़ा बेहतर विकल्प ... [एसएस 2000 विकल्पों के बारे में सीएमएसजेआर के प्रश्न के लिए विचार] (http://msdn.microsoft.com/ en-us/पुस्तकालय/aa259187% 28SQL.80% 29.aspx)। –

+0

जाओ @ पीटर! आपके लिए +1 – cmsjr

1

चूंकि यह धागा मेरे लिए बहुत उपयोगी था, मैंने सोचा कि मैं अपना समाधान साझा करूंगा।

मुझे एक समान समस्या थी, शायद इस विशिष्ट एकल-सेट तुलना से अधिक आम तौर पर लागू होती है। मैं उस तत्व की आईडी को खोजने का प्रयास कर रहा था जिसमें बहु-तत्व बाल तत्वों का एक सेट था जो बहु-तत्व वस्तुओं के एक क्वेरी सेट से मेल खाता था।

प्रासंगिक स्कीमा जानकारी है:

table events, pk id 
table solutions, pk id, fk event_id -> events 
table solution_sources, fk solutionid -> solutions 
    columns unitsourceid, alpha 

क्वेरी: आईडी 110 solution_sources कि ss_tmp में (unitsourceid, अल्फा) के सेट से मिलान के सेट है कि के साथ घटना के लिए समाधान खोजने के। (यह भी tmp तालिका के बिना किया जा सकता है, मेरा मानना ​​है कि।)

समाधान:

with solutionids as (
    select y.solutionid from (
    select ss.solutionid, count(ss.solutionid) x 
     from solutions s, solution_sources ss 
     where s.event_id = 110 and ss.solutionid = s.id 
     group by ss.solutionid 
) y where y.x = (select count(*) from ss_tmp) 
) 
select solutionids.solutionid from solutionids where 
(
select case 
    when count(*) = (select count(*) from ss_tmp) then true 
    else false 
    end 
    from 
     (SELECT unitsourceid, alpha FROM solution_sources 
      where solutionid = solutionids.solutionid 
      INTERSECT 
     SELECT unitsourceid, alpha FROM ss_tmp) x 
) 

4 मदों की एक परीक्षण क्वेरी और एक परीक्षण db कि एक मिलान समाधान था (बच्चे की एक ही नंबर के खिलाफ परीक्षण किया गया तत्व, प्रत्येक मिलान किए गए), कई पूरी तरह गैर-मिलान समाधान, और 1 समाधान जिसमें 3 मिलान करने वाले बच्चे तत्व थे, 1 समाधान जिसमें सभी 4 मिलान करने वाले बच्चे तत्व थे, साथ ही एक अतिरिक्त बच्चा, और 1 समाधान जिसमें 4 बच्चे तत्व थे जिनमें से 3 4 मिलान की क्वेरी से। केवल सच्चे मैच की आईडी वापस कर दी गई थी।

बहुत बहुत शुक्रिया -Linus

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