2012-07-02 14 views
16

मैं एक एकल SQL कथन बनाने की कोशिश कर रहा हूं जो एक ही तालिका में स्थित कई स्तंभों से अद्वितीय, गैर-शून्य मान देता है।एक ही तालिका में एकाधिक कॉलम से अलग मान चुनें

SELECT distinct tbl_data.code_1 FROM tbl_data 
     WHERE tbl_data.code_1 is not null 
UNION 
SELECT tbl_data.code_2 FROM tbl_data 
     WHERE tbl_data.code_2 is not null; 

उदाहरण के लिए, tbl_data इस प्रकार है: एबी, बीसी, डे:

id code_1 code_2 
--- -------- ---------- 
1 AB  BC 
2 BC   
3 DE  EF 
4    BC 

उपरोक्त तालिका के लिए, SQL क्वेरी दो कॉलम, अर्थात् से सभी अद्वितीय गैर-शून्य मान चाहिए , ईएफ।

मैं एसक्यूएल के लिए बिल्कुल नया हूं। काम के ऊपर मेरा बयान, लेकिन क्या इस SQL ​​कथन को लिखने का एक क्लीनर तरीका है, क्योंकि कॉलम एक ही टेबल से हैं? SubQuery तरह

+0

वह तालिका संरचना मुझे महसूस करती है कि आपका डीबी सामान्यीकृत नहीं है ... – gdoron

+4

आपको पहली क्वेरी में 'विशिष्ट' की आवश्यकता नहीं है - 'यूनियन' आपके लिए ऐसा करेगा। – Blorgbeard

+0

@gdoron: कोड विभिन्न पदनामों से मेल खाते हैं, जिन्हें वास्तव में दोहराया जा सकता है, यानी एक विशेष रिकॉर्ड में कोड 1 और 2 के लिए बीसी और बीसी हो सकती है। कोड 1 बनाम 2 का पदनाम भी महत्वपूर्ण है। विभिन्न कोडों के लिए एक तीसरी टेबल लुक-अप तालिका है। सबसे अच्छा नहीं, लेकिन मैं यही कर रहा हूं। – regulus

उत्तर

18

संदिग्ध टेक्स्ट डेटा की बजाय कोड को अपने प्रश्न को शामिल करना बेहतर है, ताकि हम सभी एक ही डेटा के साथ काम कर रहे हों। क्योंकि UNION ऑपरेटर डुप्लीकेट पंक्तियों समाप्त

CREATE TABLE tbl_data (
    id INT NOT NULL, 
    code_1 CHAR(2), 
    code_2 CHAR(2) 
); 

INSERT INTO tbl_data (
    id, 
    code_1, 
    code_2 
) 
VALUES 
    (1, 'AB', 'BC'), 
    (2, 'BC', NULL), 
    (3, 'DE', 'EF'), 
    (4, NULL, 'BC'); 

Blorgbeard के रूप में टिप्पणी की, अपने समाधान में DISTINCT खंड अनावश्यक है: यहाँ नमूना स्कीमा और डेटा मैं मान लिया है है। UNION ALL ऑपरेटर है जो डुप्लीकेट को समाप्त नहीं करता है, लेकिन यह यहां उचित नहीं है।

SELECT code_1 
FROM tbl_data 
WHERE code_1 IS NOT NULL 
UNION 
SELECT code_2 
FROM tbl_data 
WHERE code_2 IS NOT NULL; 

यह कोई फर्क नहीं पड़ता कि दो कॉलम में एक ही तालिका में कर रहे हैं:

DISTINCT खंड के बिना आपकी क्वेरी नए सिरे से लिखना इस समस्या का एक अच्छा समाधान है। समाधान अलग-अलग तालिकाओं में होने पर भी वही होगा।

आप एक ही फ़िल्टर खंड दो बार निर्दिष्ट करने के अतिरेक पसंद नहीं है, तो आप को छानने कि पहले एक आभासी तालिका में यूनियन क्वेरी संपुटित कर सकते हैं:

SELECT code 
FROM (
    SELECT code_1 
    FROM tbl_data 
    UNION 
    SELECT code_2 
    FROM tbl_data 
) AS DistinctCodes (code) 
WHERE code IS NOT NULL; 

मैं दूसरा अधिक बदसूरत की वाक्य रचना को खोजने , लेकिन यह तार्किक रूप से neater है। लेकिन कौन सा बेहतर प्रदर्शन करता है?

मैं एक sqlfiddle यह दर्शाता है कि कि SQL सर्वर 2005 की क्वेरी अनुकूलक दो अलग-अलग प्रश्नों के लिए एक ही कार्य योजना लागू करके पैदा करता बनाया:

The query optimizer produces this execution plan for both queries: two table scans, a concatenation, a distinct sort, and a select.

एसक्यूएल सर्वर दो प्रश्नों के लिए एक ही कार्य योजना लागू करके उत्पन्न करता है, तो वे व्यावहारिक रूप से साथ ही तर्कसंगत समकक्ष हैं।

अपने प्रश्न में क्वेरी के लिये कार्य योजना के लिए ऊपर की तुलना करें:

The DISTINCT clause makes SQL Server 2005 perform a redundant sort operation.

DISTINCT खंड SQL सर्वर 2005 एक निरर्थक तरह कार्रवाई करने में आता है, क्योंकि क्वेरी अनुकूलक है कि किसी भी डुप्लिकेट नहीं जानता है DISTINCT द्वारा फ़िल्टर पहली क्वेरी में बाद में वैसे भी UNION द्वारा फ़िल्टर किया जाएगा।

यह क्वेरी तर्कसंगत रूप से अन्य दो के बराबर है, लेकिन अनावश्यक संचालन इसे कम कुशल बनाता है। एक बड़े डेटा सेट पर, मैं आपकी क्वेरी लंबे समय तक लेने के लिए एक परिणाम के दो यहाँ से सेट वापस जाने के लिए उम्मीद करेंगे। इसके लिए मेरा शब्द मत लो; सुनिश्चित करने के लिए अपने पर्यावरण में प्रयोग करें!

+0

इस स्पष्टीकरण के लिए धन्यवाद! – regulus

+0

सबसे अच्छे उत्तरों में से एक मुझे लगता है कि मैंने कभी भी एसओ पर पढ़ा है। उत्कृष्ट विवरण और उदाहरण, और परीक्षा परिणाम। – htm11h

4

कोशिश कुछ:

SELECT derivedtable.NewColumn 
FROM 
(
    SELECT code_1 as NewColumn FROM tbl_data 
    UNION 
    SELECT code_2 as NewColumn FROM tbl_data 
) derivedtable 
WHERE derivedtable.NewColumn IS NOT NULL 

UNION पहले से ही संयुक्त क्वेरी से DISTINCT मान देता है।

+0

इस उदाहरण के लिए धन्यवाद! – regulus

+0

धन्यवाद! सही जवाब लगता है मैं देख रहा हूँ! – NidhinSPradeep

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