क्या मैं एक JOIN स्थिति में CASE स्टेटमेंट का उपयोग कर सकता हूं?


141

निम्न छवि Microsoft SQL Server 2008 R2 सिस्टम दृश्य का एक हिस्सा है। छवि से हम देख सकते हैं कि के बीच संबंध sys.partitionsऔर sys.allocation_unitsमूल्य पर निर्भर करता है sys.allocation_units.type। इसलिए उन्हें एक साथ मिलाने के लिए मैं कुछ ऐसा लिखूंगा:

SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id = p.hobt_id 
               WHEN a.type IN (2)
                   THEN a.container_id = p.partition_id
               END 

लेकिन ऊपरी कोड एक सिंटैक्स त्रुटि देता है। मुझे लगता है कि CASEबयान के कारण है । क्या कोई थोड़ा समझाने में मदद कर सकता है?


त्रुटि संदेश जोड़ें:

एमएसजी 102, स्तर 15, राज्य 1, लाइन 6 '=' के पास गलत सिंटैक्स।

यह छवि है


36
इस सुंदर डीबी आरेख को बनाने के लिए आपने किस सॉफ्टवेयर का उपयोग किया?
LearnByReading

2
@LearnByReading क्या आपको कभी पता चला कि किस सॉफ्टवेयर का इस्तेमाल किया गया था?
उपयोगकर्ता 632716

1
@ User632716 दुर्भाग्य से नहीं!
LearnByReading

2
@ User632716 हालांकि मुझे वाकई लगता है कि यह MySQL कार्यक्षेत्र था। लेकिन मुझे कभी कोई प्रतिक्रिया नहीं मिली
LearnByReading

@LearnByReading मुझे कोई पता नहीं है। यह Microsoft द्वारा प्रदान किया गया है।
एक शिक्षार्थी

जवाबों:


223

एक CASEअभिव्यक्ति THENखंड के भाग से एक मान लौटाती है । आप इसे इस प्रकार उपयोग कर सकते हैं:

SELECT  * 
FROM    sys.indexes i 
    JOIN sys.partitions p 
        ON i.index_id = p.index_id  
    JOIN sys.allocation_units a 
        ON CASE 
           WHEN a.type IN (1, 3) AND a.container_id = p.hobt_id THEN 1
           WHEN a.type IN (2) AND a.container_id = p.partition_id THEN 1
           ELSE 0
           END = 1

ध्यान दें कि आपको लौटे हुए मूल्य के साथ कुछ करने की आवश्यकता है, उदाहरण के लिए इसकी तुलना 1 से करें। आपके कथन ने समानता के लिए असाइनमेंट या परीक्षण के मूल्य को वापस करने का प्रयास किया है, जिसमें से कोई भी CASE/ THENखंड के संदर्भ में कोई मतलब नहीं है । (यदि BOOLEANएक डेटाटाइप था तो समानता के लिए परीक्षण का मतलब होगा।)


@ हाओ धन्यवाद कि मेरे लिए काम किया ... लेकिन समस्या यह है कि जब मैं ऐसा करता हूं तो स्थितियां गिर जाती हैं ... कृपया मुझे बताएं कि इसे कैसे तोड़ूं?
सागर टंडेल

1
@ सागरटांडेल - क्षमा करें, मुझे समझ में नहीं आया कि "एक गिरावट के माध्यम से" और "मैं इसे कैसे तोड़ूं"। क्या आप अपनी टिप्पणी स्पष्ट कर सकते हैं? (हाल ही में सबा के डाइव से सामने आया। शायद नाइट्रॉक्स हो सकता है।)
HABO

यह उन सभी स्थितियों के लिए जाँच करता है जो मुझे नहीं चाहिए। मैं यह चाहता हूं कि यह एक बार मैच से बाहर हो जाए।
सागर टंडेल

3
@ सागरटैंडल - एमएसडीएन से : "CASE स्टेटमेंट क्रमिक रूप से इसकी स्थितियों का मूल्यांकन करता है और पहली शर्त के साथ बंद हो जाता है जिसकी स्थिति संतुष्ट है।"। यदि आप सभी सम्मिलित पंक्तियों को चाहते हैं जो स्पष्ट रूप से बताई गई किसी भी स्थिति से मेल नहीं खाती हैं, तो बस पूंछ के छोर को बदल = 1दें = 0, लेकिन मुझे नहीं लगता कि आप परिणाम पसंद करेंगे।
एचएबीओ

JOIN sys.allocation_units ON ON CASE जब a.type IN (1, 3) और a.container_id = p.hobt_id है, तो 1 a.type IN (2) और a.container_id = p.partition_id 1 ELSE 0 END = 1 पर टाइप करें। क्या आप इसे अपने समाधान के ऊपर इकाई ढांचे में लिख सकते हैं
r.hamd

36

इसके बजाय, आप बस दोनों तालिकाओं में शामिल हों, और अपने सेलेक्ट क्लॉज में, उस मैच से डेटा लौटाएं:

मेरा सुझाव है कि आप इस लिंक के माध्यम से जाने के लिए कंडीशनल जॉइन इन एसक्यूएल सर्वर और टी-एसक्यूएल केस स्टेटमेंट इन ए जॉय ऑन क्लॉज

जैसे

    SELECT  *
FROM    sys.indexes i
        JOIN sys.partitions p
            ON i.index_id = p.index_id 
        JOIN sys.allocation_units a
            ON a.container_id =
            CASE
               WHEN a.type IN (1, 3)
                   THEN  p.hobt_id 
               WHEN a.type IN (2)
                   THEN p.partition_id
               END 

संपादित करें: टिप्पणियों के अनुसार।

आप शामिल होने की स्थिति को निर्दिष्ट नहीं कर सकते हैं जैसा कि आप कर रहे हैं .. ऊपर क्वेरी की जांच करें जिसमें कोई त्रुटि नहीं है। मैंने सामान्य कॉलम को निकाल लिया है और सही कॉलम वैल्यू का मूल्यांकन हालत पर किया जाएगा।


1
क्या conditional joinमतलब है? प्रत्येक जॉइन (क्रॉस को छोड़कर) एक सशर्त है। यह मामला किसी अन्य से अलग कैसे है? आपके नमूने में कंडीशन के साथ आंतरिक रूप से जुड़ना है, साथ ही OPs क्वेरी में कंडीशन के साथ जुड़ना है।
झटके

@ अक्ष: मैं सहमत हूँ, यह भ्रामक लगता है। मेरा मानना ​​है, इस संदर्भ में एक सशर्त जुड़ाव का अर्थ है एक ऐसी संलिप्तता जिसकी स्थिति अन्य शर्त पर निर्भर करती है।
एंड्री एम

@Andriy एम: तुच्छ स्थिति के लिए किसी अन्य शब्द के बारे में सोचने का कोई कारण OR?
zerkms

@ अक्ष: एर, हाँ, यह है क्योंकि यह भ्रामक लगता है। :) लेकिन मेरा मानना ​​है कि आप से पूछना था कि क्या कोई कारण नहीं था कि किसी अन्य शब्द के बारे में सोचा जाए, जिस स्थिति में मैं निश्चित नहीं हो सकता। यदि आप मेरे कारण पूछ रहे हैं , तो ठीक है, मुझे लगता है कि मुझे अभी पर्याप्त परेशान नहीं किया जा सकता है। :) वैकल्पिक स्थितियों के साथ जुड़ने के बारे में कैसे ? मुझे डर है कि मैं शब्दों को गढ़ने में बहुत अच्छा नहीं हूँ। ध्यान दें, हालांकि, वैचारिक रूप से यह "सशर्त स्थिति" के बारे में है, न कि "स्थिति के साथ OR" के बारे में । उपयोग करना ORइसे लागू करने का केवल एक तरीका है।
एंड्री एम

@Andriy एम: ठीक है। लेकिन व्यक्तिगत रूप से मुझे अभी भी 1 और 2 या 1 के साथ तुच्छ स्थिति के लिए एक नाम देने का कारण नहीं दिखता है । यह एक नियमित क्वेरी है जिसमें ऐसा कुछ भी नहीं है जो इसे किसी अन्य से अलग करता है। ORANDsCASE
झटके

17

इसे इस्तेमाल करे:

...JOIN sys.allocation_units a ON 
  (a.type=2 AND a.container_id = p.partition_id)
  OR (a.type IN (1, 3) AND a.container_id = p.hobt_id)

भले ही यह काम करेगा - प्रश्न में क्वेरी पूरी तरह से वैध लगती है। इसलिए अभी भी यह स्पष्ट नहीं करता है कि ओपी कोड में क्या गड़बड़ है
झकरम

10

मुझे लगता है कि आपको दो केस स्टेटमेंट चाहिए:

SELECT  *
FROM    sys.indexes i
    JOIN sys.partitions p
        ON i.index_id = p.index_id 
    JOIN sys.allocation_units a
        ON 
        -- left side of join on statement
            CASE
               WHEN a.type IN (1, 3)
                   THEN a.container_id
               WHEN a.type IN (2)
                   THEN a.container_id
            END 
        = 
        -- right side of join on statement
            CASE
               WHEN a.type IN (1, 3)
                   THEN p.hobt_id
               WHEN a.type IN (2)
                   THEN p.partition_id
            END             

यह है क्योंकि:

  • CASE कथन END पर एकल मान लौटाता है
  • ऑन स्टेटमेंट दो मूल्यों की तुलना करता है
  • आपका CASE कथन CASE कथन के अंदर तुलना कर रहा था । मुझे लगता है कि यदि आप अपने चयन विवरण को अपने चयन में रखते हैं तो आपको एक बूलियन '1' या '0' मिलेगा जो यह दर्शाता है कि क्या CASE कथन सही या गलत का मूल्यांकन करता है

5

मैंने आपका उदाहरण लिया और इसे संपादित किया:

SELECT  *
FROM    sys.indexes i
    JOIN sys.partitions p
        ON i.index_id = p.index_id 
    JOIN sys.allocation_units a
        ON a.container_id = (CASE
           WHEN a.type IN (1, 3)
               THEN p.hobt_id 
           WHEN a.type IN (2)
               THEN p.partition_id
           ELSE NULL
           END)

1

यह अच्छा लगता है

https://bytes.com/topic/sql-server/answers/881862-joining-different-tables-based-condition

FROM YourMainTable
LEFT JOIN AirportCity DepCity ON @TravelType = 'A' and DepFrom =  DepCity.Code
LEFT JOIN AirportCity DepCity ON @TravelType = 'B' and SomeOtherColumn = SomeOtherColumnFromSomeOtherTable

यह कोशिश कर रहा हूं कि मुझे एक त्रुटि मिल रही है: सहसंबंध नाम 'xx' एक FROM खंड में कई बार निर्दिष्ट किया गया है।
एटिएन

1

हाँ तुम कर सकते हो। यहाँ एक उदाहरण है।

SELECT a.*
FROM TableA a
LEFT OUTER JOIN TableB j1 ON  (CASE WHEN LEN(COALESCE(a.NoBatiment, '')) = 3 
                                THEN RTRIM(a.NoBatiment) + '0' 
                                ELSE a.NoBatiment END ) = j1.ColumnName 

1
हालांकि यह कोड प्रश्न को हल कर सकता है, जिसमें यह भी बताया गया है कि यह समस्या कैसे और क्यों हल करती है, इससे वास्तव में आपके पोस्ट की गुणवत्ता को बेहतर बनाने में मदद मिलेगी, और संभवत: अधिक वोट मिले। याद रखें कि आप भविष्य में पाठकों के लिए सवाल का जवाब दे रहे हैं, न कि केवल उस व्यक्ति से जो अब पूछ रहा है। कृपया स्पष्टीकरण जोड़ने के लिए अपने उत्तर को संपादित करें और संकेत दें कि क्या सीमाएँ और मान्यताएँ लागू होती हैं।
डबल-बीप

0

DonkeyKong का उदाहरण लिया।

समस्या यह है कि मुझे घोषित चर का उपयोग करने की आवश्यकता है। यह आपके बाएं और दाएं-बाएं हाथ को आपके द्वारा तुलना करने की आवश्यकता के बारे में बताता है। यह SSRS रिपोर्ट का समर्थन करने के लिए है, जहां उपयोगकर्ता द्वारा चयन के आधार पर विभिन्न क्षेत्रों को जोड़ा जाना चाहिए।

प्रारंभिक मामला चयन के आधार पर क्षेत्र की पसंद निर्धारित करता है और फिर मैं उस क्षेत्र को सेट कर सकता हूं जिसे मुझे शामिल होने के लिए मैच करने की आवश्यकता है।

यदि दूसरे चर को विभिन्न क्षेत्रों से चुनने की आवश्यकता है, तो दाएं हाथ के लिए एक दूसरा केस स्टेटमेंट जोड़ा जा सकता है

LEFT OUTER JOIN Dashboard_Group_Level_Matching ON
       case
         when @Level  = 'lvl1' then  cw.Lvl1
         when @Level  = 'lvl2' then  cw.Lvl2
         when @Level  = 'lvl3' then  cw.Lvl3
       end
    = Dashboard_Group_Level_Matching.Dashboard_Level_Name

0

यहाँ मैंने दो भिन्न परिणाम सेटों में अंतर की तुलना की है:

SELECT main.ColumnName, compare.Value PreviousValue,  main.Value CurrentValue
FROM 
(
    SELECT 'Name' AS ColumnName, 'John' as Value UNION ALL
    SELECT 'UserName' AS ColumnName, 'jh001' as Value UNION ALL
    SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
    SELECT 'Phone' AS ColumnName, NULL as Value UNION ALL
    SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
    SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
    SELECT 'IsActive' AS ColumnName, '1' as Value
) main
INNER JOIN
(
    SELECT 'Name' AS ColumnName, 'Rahul' as Value UNION ALL
    SELECT 'UserName' AS ColumnName, 'rh001' as Value UNION ALL
    SELECT 'Department' AS ColumnName, 'HR' as Value UNION ALL
    SELECT 'Phone' AS ColumnName, '01722112233' as Value UNION ALL
    SELECT 'DOB' AS ColumnName, '1993-01-01' as Value UNION ALL
    SELECT 'CreateDate' AS ColumnName, '2017-01-01' as Value UNION ALL
    SELECT 'IsActive' AS ColumnName, '1' as Value
) compare
ON main.ColumnName = compare.ColumnName AND
CASE 
    WHEN main.Value IS NULL AND compare.Value IS NULL THEN 0
    WHEN main.Value IS NULL AND compare.Value IS NOT NULL THEN 1
    WHEN main.Value IS NOT NULL AND compare.Value IS NULL THEN 1
    WHEN main.Value <> compare.Value THEN 1
END = 1 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.