2009-02-12 20 views
37

जब मैं SQL वाक्यविन्यास की बात करता हूं तो मैं नोब हूं।मैं 2 चयन विवरणों को एक में कैसे जोड़ूं?

मैं और पंक्तियों के बहुत निश्चित रूप से कॉलम युक्त तालिका है:

 AAA BBB CCC DDD 
----------------------- 
Row1 | 1 A D X 
Row2 | 2 B C X 
Row3 | 3 C D Z 

अब मैं एक उन्नत का चयन बयान है कि मुझे इस संयुक्त (छद्म SQLish देता है बनाना चाहते हैं: पी कहते हैं कि यह इस तरह दिखता है की सुविधा देता है यहाँ):

select 'Test1', * from TABLE Where CCC='D' AND DDD='X' 
select 'Test2', * from TABLE Where CCC<>'D' AND DDD='X' 

उत्पादन होगा:

Test1, 1, A, D, X 
Test2, 2, B, C, X 

मैं उन दो चुनिंदा वक्तव्यों को एक अच्छे चयन कथन में कैसे जोड़ूं?

क्या यह काम करेगा यदि मैंने नीचे SQL की जटिलता की है (क्योंकि मेरे स्वयं के SQL कथन में एक मौजूदा कथन है)? मैं सिर्फ यह जानना चाहता हूं कि मैं चयनों को कैसे जोड़ सकता हूं और फिर इसे अपने कुछ और उन्नत एसक्यूएल पर लागू करने का प्रयास करता हूं।

select Status, * from WorkItems t1 
where exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1)) 
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00' 

जो मुझे एक परिणाम देता है:

select 'Test1', * from TABLE Where CCC='D' AND DDD='X' AND exists(select ...) 
select 'Test2', * from TABLE Where CCC<>'D' AND DDD='X' AND exists(select ...) 




मेरा असली SQL विवरण इस एक है। लेकिन मैं इसे एक अतिरिक्त और अंत में इस चयन कथन की एक प्रति के साथ जोड़ना चाहता हूं और 'स्थिति' फ़ील्ड को 'हटाया गया' जैसी स्ट्रिंग के साथ बदल दिया जाएगा।

select 'DELETED', * from WorkItems t1 
where exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1)) 
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00' 
AND NOT (BoolField05=1) 
+1

+1 जो एक बेहद अच्छी तरह से पूछे जाने वाले प्रश्न –

उत्तर

55

आपके पास दो विकल्प यहाँ है। ,

select 
    'Test1', * 
from 
    TABLE 
Where 
    CCC='D' AND DDD='X' AND exists(select ...) 
UNION 
select 
    'Test2', * 
from 
    TABLE 
Where 
    CCC<>'D' AND DDD='X' AND exists(select ...) 

यह एक मुद्दा हो सकता है कि आप जा रहे हैं: पहले दो परिणाम सेट जो 'Test1' या 'Test2' WHERE खंड में स्थिति के आधार पर सेट हो जाएगा, और फिर उन्हें एक साथ UNION है तालिका को दो बार प्रभावी ढंग से स्कैन/तलाशने के लिए।

अन्य समाधान एक बार तालिका में शर्तों के आधार पर तालिका से चयन करने के लिए, और सेट 'Test1' या 'Test2' होगा:

select 
    case 
     when CCC='D' AND DDD='X' AND exists(select ...) then 'Test1' 
     when CCC<>'D' AND DDD='X' AND exists(select ...) then 'Test2' 
    end, 
    * 
from 
    TABLE 
Where 
    (CCC='D' AND DDD='X' AND exists(select ...)) or 
    (CCC<>'D' AND DDD='X' AND exists(select ...)) 

पकड़ यहाँ जा रहा है कि आप डुप्लिकेट करना होगा CASE कथन और WHERE कथन में फ़िल्टर की स्थिति।

+0

धन्यवाद (एमएस एसक्यूएल सर्वर 2005 का उपयोग कर रहा हूँ)। ऐसा लगता है कि मैं यही देख रहा हूं। यूनियन दो बार स्कैन करता है, लेकिन मैं इसके साथ रह सकता हूं। और मुझे नहीं पता था कि CASE स्टेटमेंट का उपयोग किया जा सकता है। – Wolf5

9

वे एक ही मेज से कर रहे हैं, मुझे लगता है कि UNION आदेश आप देख रहे हैं है।

(यदि आप कभी भी अलग तालिकाओं के कॉलम के मानों का चयन करना चाहते हैं तो आप JOIN पर बजाय दिखना चाहिए ...)

1
select Status, * from WorkItems t1 
where exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1)) 
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00' 

UNION 

select 'DELETED', * from WorkItems t1 
where exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1)) 
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00' 
AND NOT (BoolField05=1) 

शायद कि चाल करना चाहते हैं। हालांकि मैं इसे यहां से परीक्षण नहीं कर सकता, और मुझे यकीन नहीं है कि आप किस SQL ​​के संस्करण के खिलाफ काम कर रहे हैं।

1

The Union command is what you need. यदि वह काम नहीं करता, तो आप परिष्कृत करने के लिए क्या पर्यावरण में हो पड़ सकता है।

1

चयन में एक मामले का उपयोग करें और जहां करीब एक या

कुछ इस तरह का उपयोग करते हैं, मैं इसे परीक्षण नहीं किया था, लेकिन यह काम करना चाहिए, मुझे लगता है कि ...

select case when CCC='D' then 'test1' else 'test2' end, * 
from table 
where (CCC='D' AND DDD='X') or (CCC<>'D' AND DDD='X') 
1

मैं लगता है कि आप जो खोज रहे हैं रहा है:

SELECT CASE WHEN BoolField05 = 1 THEN Status ELSE 'DELETED' END AS MyStatus, t1.* 
FROM WorkItems t1 
WHERE (TextField01, TimeStamp) IN(
    SELECT TextField01, MAX(TimeStamp) 
    FROM WorkItems t2 
    GROUP BY t2.TextField01 
) 
AND TimeStamp > '2009-02-12 18:00:00' 

आप Oracle में या एसक्यूएल 2005 एमएस में हैं और इसके बाद के संस्करण है, तो आप कर सकता है, तो:

SELECT * 
FROM (
    SELECT CASE WHEN BoolField05 = 1 THEN Status ELSE 'DELETED' END AS MyStatus, t1.*, 
    ROW_NUMBER() OVER (PARTITION BY TextField01 ORDER BY TimeStamp DESC) AS rn 
    FROM WorkItems t1 
) to 
WHERE rn = 1 

, यह अधिक कुशल है।

2

इनपुट के लिए धन्यवाद। सामान है कि यहाँ उल्लेख किया गया है की कोशिश की और इन 2 हैं मैं काम करने के लिए मिल गया:

(
select 'OK', * from WorkItems t1 
where exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1)) 
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00' 
AND (BoolField05=1) 
) 
UNION 
(
select 'DEL', * from WorkItems t1 
where exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1)) 
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00' 
AND NOT (BoolField05=1) 
) 

और

select 
    case 
     when 
      (BoolField05=1) 
    then 'OK' 
    else 'DEL' 
     end, 
     * 
from WorkItems t1 
Where 
      exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1)) 
      AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
      AND TimeStamp>'2009-02-12 18:00:00' 

कौन सा के इन (संपादित सबसे कारगर होगा: यह के रूप में दूसरे स्थान पर स्कैन तालिका एक बार), और क्या यह इसे और अधिक कुशल बनाने के लिए संभव है? (BoolField = 1) वास्तव में एक चर (dyn sql) है जिसमें तालिका पर कोई भी कथन शामिल हो सकता है।

मैं एमएस एसक्यूएल 2005 पर चल रहा हूं। क्वास्नोई उदाहरणों का प्रयास किया लेकिन उम्मीद के अनुसार काम नहीं किया।

+0

यह ठोस है। धन्यवाद :) – Jordon

0
select t1.* from 
(select * from TABLE Where CCC='D' AND DDD='X') as t1, 
(select * from TABLE Where CCC<>'D' AND DDD='X') as t2 

ऐसा करने का एक और तरीका!

+0

2 पंक्तियों के साथ एक कॉलम तालिका का सरल परीक्षण और टी 2 के रूप में पहले का चयन करने के लिए उस क्वेरी का उपयोग करके और टी 2 के रूप में दूसरा, विफल रहता है, केवल टी 1 देता है। – Wolf5

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