2015-09-09 4 views
7

मैं एसक्यूएल सर्वर 2012T-SQL प्रकरण बयान अजीब व्यवहार

उपयोग कर रहा हूँ मैं रेंज में यादृच्छिक-ish नंबरों की सूची प्राप्त करने के लिए [1,3 निम्नलिखित करते हैं ], यह ठीक काम करता है:

SELECT TOP 100 
    ABS(CHECKSUM(NEWID()))%3 + 1 [value_of_rand] 
FROM sys.objects 

और मुझे इस तरह की अच्छी चीजें मिलती हैं (सभी 1 और 3 के बीच)।

3 
2 
2 
2 
1 
....etc. 

लेकिन अगर मैं तो एक मामला बयान में है कि एक ही श्रृंखलित यादृच्छिक-मूल्य फ़ंक्शन के परिणाम में कहें, यह जाहिरा तौर पर केवल मूल्यों 1,2,3 का उत्पादन नहीं करता।

SELECT TOP 100 
    CASE (ABS(CHECKSUM(NEWID()))%3 + 1) 
     WHEN 1 
      THEN 'one' 
     WHEN 2 
      THEN 'two' 
     WHEN 3 
      THEN 'three' 
     ELSE 
      'that is strange' 
    END [value_of_case] 
FROM sys.objects 

यह आउटपुट:

three 
that is strange 
that is strange 
one 
two 
...etc 

क्या मैं गलत यहाँ कर रहा हूँ?

+0

यह हो सकता है कि ऐसा नहीं है जब नंबर पेश इसे गोलाई है, लेकिन जब मूल्यांकन कर? इसे एक चर और डिबगिंग/उस मूल्य को फेंकने का प्रयास करें जहां आपके पास "अजीब है"। – Dane

+0

यदि मैं इसे एक चर के लिए असाइन करता हूं और फिर उस चर के विरुद्ध केस स्टेटमेंट करता हूं, तो यह ठीक काम करता है, कोई अजीबता नहीं। हालांकि, मुझे लगता है कि इसे डिबग करने की आपकी विधि संभव नहीं है। मुझे यह कहते हुए एक त्रुटि मिलती है कि "एक चयन कथन जो एक चर को मान निर्दिष्ट करता है उसे डेटा-पुनर्प्राप्ति संचालन के साथ जोड़ा जाना चाहिए।" अगर मैं ऐसा कुछ करने की कोशिश करता हूं: DECLARE @a int; @ ए = (एबीएस (चेकसम (न्यूड()))% 3 + 1), केस @ ए \t जब 1 फिर 'एक' कब 2 'दो' \t जब 3 'तीन' \t ईएलएसई अजीब: '+ कास्ट (@a वर्चर (अधिकतम)) END – Anssssss

+0

आप हमेशा पूरे 'WHEN 3' मामले को हटा सकते हैं और' ईएलएसई ' –

उत्तर

7

आपका:

SELECT TOP 100 
    CASE (ABS(CHECKSUM(NEWID()))%3 + 1) 
     WHEN 1 
      THEN 'one' 
     WHEN 2 
      THEN 'two' 
     WHEN 3 
      THEN 'three' 
     ELSE 
      'that is strange' 
    END [value_of_case] 
FROM sys.objects 

वास्तव में मार डाला:

SELECT TOP 100 
    CASE 
     WHEN (ABS(CHECKSUM(NEWID()))%3 + 1) = 1 THEN 'one' 
     WHEN (ABS(CHECKSUM(NEWID()))%3 + 1) = 2 THEN 'two' 
     WHEN (ABS(CHECKSUM(NEWID()))%3 + 1) = 3 THEN 'three' 
     ELSE 'that is strange' 
    END [value_of_case] 
FROM sys.objects; 

मूल रूप से आपकी अभिव्यक्ति गैर नियतात्मक है और हर बार मूल्यांकन किया जाता है ताकि आप ELSE clause साथ खत्म हो सकता है। तो कोई बग या पकड़ नहीं है, बस आप इसे परिवर्तनीय अभिव्यक्ति के साथ उपयोग करते हैं और यह पूरी तरह से सामान्य व्यवहार है।

यह COALESCE syntactic-sugar

COALESCE अभिव्यक्ति की तरह एक ही कक्षा है मामला अभिव्यक्ति के लिए एक वाक्यात्मक शॉर्टकट है। यही कारण है, कोड COALESCE (expression1, ... एन) निम्नलिखित मामला अभिव्यक्ति के रूप में क्वेरी अनुकूलक द्वारा फिर से लिखा है:

मामला

WHEN (expression1 IS NOT NULL) तो expression1

जब (अभिव्यक्ति 2 पूर्ण नहीं है) तो अभिव्यक्ति 2

...

वरना expressionN

अंत

इसका मतलब है कि इनपुट मानों (expression1, expression2, expressionN, आदि) कई बार मूल्यांकन किया जाएगा। इसके अलावा, एसक्यूएल मानक के साथ अनुपालन, एक मूल्य अभिव्यक्ति जिसमें सबक्वायरी शामिल है, गैर-निर्धारिती माना जाता है और सबक्वायरी का मूल्यांकन दो बार किया जाता है। किसी भी मामले में, के बीच पहले मूल्यांकन और बाद के मूल्यांकन के बीच अलग-अलग परिणाम लौटाए जा सकते हैं।

संपादित करें:

समाधान: SqlFiddle

SELECT TOP 100 
    CASE t.col 
     WHEN 1  THEN 'one' 
     WHEN 2  THEN 'two' 
     WHEN 3  THEN 'three' 
     ELSE  'that is strange' 
    END [value_of_case] 
FROM sys.objects 
CROSS APPLY (SELECT ABS(CHECKSUM(NEWID()))%3 + 1) AS t(col) 
+0

@Anssssss मेरा अद्यतन उत्तर देखें, समाधान – lad2025

+0

है [CASE] (https://msdn.microsoft.com/en-us/library/ms181765.aspx) के लिए पृष्ठ को देखकर यह कहता है, ** सरल केस अभिव्यक्ति के तहत : ** "मूल्यांकन * इनपुट_एक्सप्रेस *, और फिर निर्दिष्ट क्रम में, प्रत्येक WHEN खंड के लिए * input_expression * = * when_expression * का मूल्यांकन करता है।" यह एक प्रलेखन त्रुटि हो सकती है, और आपकी व्याख्या सही प्रतीत होती है, लेकिन क्या आपने देखा है कि वास्तव में क्वेरी को एक बार सबमिट करने के तरीके को फिर से लिखा जा रहा है? बस उत्सुक। –

+0

@srutzky 'COALESCE' के बारे में कनेक्ट त्रुटि पर है जो केस के रूप में अनचाहे है, यह वही मामला है। 'COALESCE' में दस्तावेज़ीकरण में चेतावनी है,' केस 'नहीं :(https://connect.microsoft.com/SQLServer/feedback/details/546437/ – lad2025

1

मैं आपको नहीं बता सकता कि यह वास्तव में अजीब क्यों है, लेकिन मैं आपको एक कामकाज दे सकता हूं। उन्हें

;with rndsrc(value_of_rand) as 
(
SELECT TOP 100 
    ABS(CHECKSUM(NEWID()))%3 + 1 
FROM sys.objects 
) 
SELECT TOP 100 
CASE value_of_rand 
    WHEN 1 
     THEN 'one' 
    WHEN 2 
     THEN 'two' 
    WHEN 3 
     THEN 'three' 
    ELSE 
     'that is strange' 
END [value_of_case] 
from rndsrc 

उपयोग करने के लिए कोई और अधिक प्रयास करने से पहले एक CTE में यादृच्छिक मान का चयन करें

+0

में 'तीन' डाल सकते हैं यह काम करता है, लेकिन मुझे यकीन नहीं है कि यह कितना विश्वसनीय है। ऑप्टिमाइज़र को चीजों को चारों ओर स्थानांतरित करने की इजाजत दी जाती है क्योंकि यह फिट दिखाई देती है और भविष्य में इसे फिर से ऑर्डर कर सकती है, हालांकि, मुझे संदेह है कि जब तक आप सीटीई या सबक्वायरी में अभिव्यक्ति के साथ 'टॉप 100' रखते हैं, तो यह शायद रहेगा स्थिर। – RBarryYoung

+0

@Jamiec यही कारण है कि http://stackoverflow.com/a/32485383/5070879 – lad2025

2

मुझे लगता है कि समस्या आप यहाँ सामना कर रहे हैं कि (ABS(CHECKSUM(NEWID()))%3 + 1) एक मूल्य नहीं है "कि अजीब बात है", यह एक है अभिव्यक्ति और एसक्यूएल के पास जब भी चाहें पुन: मूल्यांकन करने का विकल्प होता है। आप अतिरिक्त संश्लेषण या सीटीई को हटाने जैसे विभिन्न वाक्य रचनात्मक चीजों को आजमा सकते हैं। इससे इसे दूर (अब के लिए) हो सकता है, लेकिन ऐसा नहीं हो सकता है, क्योंकि तर्कसंगत रूप से यह अनुकूलक के लिए एक ही अनुरोध की तरह दिखता है।

मुझे लगता है कि इसे रोकने के लिए एकमात्र निश्चित-अग्नि, समर्थित तरीका इसे पहले सहेजना होगा (एक अस्थायी तालिका या वास्तविक में) और फिर सहेजे गए मानों के संदर्भ में दूसरी क्वेरी का उपयोग करें।

+0

लेकिन यह अभिव्यक्ति संभवतः एक मूल्य कैसे उत्पन्न कर सकती है जो CASE कथन की ईएलएसई शाखा को हिट करने का कारण बनती है? – Anssssss

+1

@Anssssss क्योंकि 'केस' * अभिव्यक्ति * सी 'स्विच' कथन की तरह नहीं है, अभिव्यक्ति का प्रत्येक 'केस' सशर्त परीक्षण पर फिर से मूल्यांकन किया जा सकता है और विभिन्न मानों के साथ आ सकता है .. – RBarryYoung

+0

मुझे समझ में नहीं आता है। क्या आप कह रहे हैं कि (एबीएस (चेक्सम (न्यूआईडी()))% 3 + 1) 1,2, या 3 के अलावा कुछ और उत्पादन कर सकता है? – Anssssss

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