SQL परिकलित फ़ील्ड का चयन और समूह द्वारा दोनों खंड में


11

अक्सर अपने एमएस SQL ​​सर्वर डेटाबेस को क्वेरी करने में, मुझे इस तरह से एक परिकलित फ़ील्ड बनाने की आवश्यकता होती है

(CASE WHEN A.type = 'Workover' THEN 'Workover' 
      ELSE (CASE WHEN substring(C.category, 2, 1) = 'D' THEN 'Drilling' 
                 WHEN substring(C.category, 2, 1) = 'C' THEN 'Completion' 
                 WHEN substring(C.category, 2, 1) = 'W' THEN 'Workover' 
                 ELSE 'Other' 
            END)
END)

और फिर मुझे इस परिकलित फ़ील्ड (दूसरों के बीच) द्वारा अपने परिणाम समूहित करने की आवश्यकता है। इसलिए, मेरे पास SELECT और GROUP BY दोनों खंडों में समान गणना है। क्या SQL सर्वर वास्तव में इन गणनाओं को दो बार कर रहा है, या यह केवल एक बार करने के लिए पर्याप्त स्मार्ट है?

जवाबों:


13

खंडों के चयन और समूह दोनों में मेरी एक ही गणना है। क्या SQL सर्वर वास्तव में इन गणनाओं को दो बार कर रहा है, या यह केवल एक बार करने के लिए पर्याप्त स्मार्ट है?

इसका सरल उत्तर यह है कि SQL सर्वर कब, और कितनी बार के बारे में कोई सामान्य गारंटी देता है, एक अदिश अभिव्यक्ति का मूल्यांकन निष्पादन समय पर किया जाएगा।

प्लेसमेंट, निष्पादन और स्केलिंग अभिव्यक्तियों के कैशिंग के बारे में ऑप्टिमाइज़र और निष्पादन इंजन के भीतर सभी प्रकार के जटिल (और अनिर्दिष्ट) व्यवहार हैं। किताबें ऑनलाइन इस बारे में कहने के लिए बहुत कुछ नहीं है, लेकिन यह क्या कहता है यह है:

गणना स्केलर विवरण

यह उन व्यवहारों में से एक का वर्णन करता है जिन्हें मैंने पहले व्यक्त किया था, अभिव्यक्ति के निष्पादन को स्थगित कर दिया। मैंने इस ब्लॉग पोस्ट में कुछ अन्य मौजूदा व्यवहारों (जो किसी भी समय बदल सकते हैं) के बारे में लिखा था ।

एक और विचार यह है कि क्वेरी ऑप्टिमाइज़र द्वारा उपयोग किया जाने वाला लागत मॉडल वर्तमान में स्केलर अभिव्यक्तियों के लिए लागत अनुमान के तरीके में बहुत कुछ नहीं करता है । एक मजबूत लागत ढांचे के बिना, वर्तमान परिणाम व्यापक अनुमान या शुद्ध संभावना पर आधारित हैं।

बहुत ही सरल भावों के लिए, यह बहुत अंतर नहीं करता है कि क्या अभिव्यक्ति का मूल्यांकन ज्यादातर मामलों में एक बार या कई बार किया जाता है। उस ने कहा, मुझे बड़े सवालों का सामना करना पड़ा है जहां अभिव्यक्ति पर प्रतिकूल प्रभाव पड़ा है जब अभिव्यक्ति का बहुत बड़ी संख्या में बार-बार मूल्यांकन किया जाता है, या मूल्यांकन एक एकल थ्रेड पर होता है जहां निष्पादन की समानांतर शाखा में मूल्यांकन करना फायदेमंद होता। योजना।

सारांश में, वर्तमान व्यवहार अपरिभाषित है, और जो कुछ भी हुआ है, उसे जानने में आपकी मदद करने के लिए निष्पादन योजनाओं में बहुत कुछ नहीं है (और विस्तृत इंजन व्यवहारों की जांच करने के लिए डिबगर संलग्न करना हमेशा सुविधाजनक नहीं होगा, जैसा कि ब्लॉग पोस्ट में है)।

यदि आप ऐसे मामलों का सामना करते हैं जहां स्केलर मूल्यांकन प्रदर्शन के लिए समस्या है, तो Microsoft समर्थन के साथ समस्या को बढ़ाएं। यह उत्पाद के भविष्य के संस्करणों को बेहतर बनाने के लिए प्रतिक्रिया प्रदान करने का सबसे अच्छा तरीका है।


3

जैसा कि आपके प्रश्न पर टिप्पणी में कहा गया है, उत्तर है (मेरे अनुभव में, कम से कम) "हाँ"। SQL सर्वर आमतौर पर पुन: संगणना से बचने के लिए पर्याप्त स्मार्ट है। आप संभवतः SQL सर्वर प्रबंधन स्टूडियो से निष्पादन योजना दिखा कर इसे सत्यापित कर सकते हैं। प्रत्येक परिकलित फ़ील्ड निर्दिष्ट है Exprxxxxx(जहाँ xxxxx एक संख्या है)। यदि आप जानते हैं कि क्या देखना है, तो आपको यह सत्यापित करने में सक्षम होना चाहिए कि यह उसी अभिव्यक्ति का उपयोग करता है।

चर्चा में जोड़ने के लिए, आपका अन्य सौंदर्य विकल्प एक सामान्य तालिका अभिव्यक्ति है :

with [cte] as
(
    select
        (case when a.type = 'workover' then 'workover' else 
        (case when substring(c.category, 2, 1) = 'd' then 'drilling'
              when substring(c.category, 2, 1) = 'c' then 'completion'
              when substring(c.category, 2, 1) = 'w' then 'workover'
              else 'other' end)
         end)) as [group_key],
         *
    from
        [some_table]
)
select
    [group_key],
    count(*) as [count]
from
    [cte]
group by
    [group_key]

लघु उत्तर, वे कार्यात्मक रूप से एक दृश्य के समान हैं, लेकिन केवल अगले बयान में उपयोग के लिए मान्य हैं। मैं उन्हें ज्यादातर व्युत्पन्न तालिकाओं के लिए एक अधिक पठनीय विकल्प के रूप में देखता हूं क्योंकि यह घोंसले के शिकार से बचा जाता है।

हालांकि इस प्रश्न के लिए प्रासंगिक नहीं है, वे स्वयं को संदर्भित कर सकते हैं और इस तरह से पुनरावर्ती प्रश्नों का निर्माण करने के लिए उपयोग किया जा सकता है।


@ क्विक जो स्मिथ: मुझे लगता है कि आप Exprxxxxx के बारे में सही हैं, क्योंकि मैंने भी देखा है। हालाँकि, यदि मैं OpType के रूप में मैन्युअल रूप से (केस ... एंड) एक्सप्रेशन को एक नाम देता हूं, तो GROUP BY ग्रुप क्लॉज में फ़ील्ड ओपन टाइप का उपयोग करें, मुझे एक त्रुटि मिलती है कि यह एक अमान्य कॉलम नाम है।
डॉ।

दुर्भाग्य से, दो बार अभिव्यक्ति को निर्दिष्ट करने का आपका एकमात्र तरीका अक्सर उपरोक्त विधियों में से एक का उपयोग करना है: सीटीई, दृश्य या एक नेस्टेड क्वेरी।
क्विक जो स्मिथ

2
जब तक आप CROSS APPLY के बारे में भी नहीं जानते हैं ।
एंड्री एम

cross applyइस मामले में उपयोग करना थोड़ा खिंचाव है, और यह अनावश्यक रूप से आत्म-जोड़कर प्रदर्शन को नुकसान पहुंचाएगा।
क्विक जो स्मिथ

2
मुझे नहीं लगता कि आपको सुझाव मिला है। CROSS APPLYसिर्फ एक ही पंक्ति में स्तंभों से उर्फ परिभाषित करता है। किसी जुड़ने की जरूरत नहीं। जैसेSELECT COUNT(*), hilo FROM master..spt_values CROSS APPLY (VALUES(high + low)) V(hilo) GROUP BY hilo
मार्टिन स्मिथ

1

प्रदर्शन सिर्फ एक पहलू है। दूसरी मेंटेनेंस है।

व्यक्तिगत रूप से, मैं निम्नलिखित कार्य करता हूं:

SELECT T.GroupingKey, SUM(T.value)
FROM
(
    SELECT 
        A.*
        (CASE WHEN A.type = 'Workover' THEN 'Workover' ELSE 
        (CASE WHEN substring(C.category, 2, 1) = 'D' THEN 'Drilling' WHEN substring(C.category, 2, 1) = 'C' THEN 'Completion' WHEN substring(C.category, 2, 1) = 'W' THEN 'Workover' ELSE 'Other' END)
        END) AS GroupingKey
    FROM Table AS A
) AS T

GROUP BY T.GroupingKey

अपडेट करें:

यदि आप नेस्टिंग करना पसंद नहीं करते हैं, तो आप प्रत्येक तालिका के लिए व्यू बना सकते हैं जहाँ आपको जटिल अभिव्यक्तियों का उपयोग करने की आवश्यकता है।

CREATE VIEW TableExtended
AS 
SELECT 
    A.*
    (CASE WHEN A.type = 'Workover' THEN 'Workover' ELSE 
    (CASE WHEN substring(C.category, 2, 1) = 'D' THEN 'Drilling' WHEN substring(C.category, 2, 1) = 'C' THEN 'Completion' WHEN substring(C.category, 2, 1) = 'W' THEN 'Workover' ELSE 'Other' END)
    END) AS GroupingKey
FROM Table AS A

तब आप अतिरिक्त नेस्टिंग किए बिना चयन कर सकते थे;

SELECT GroupingKey, SUM(value)
FROM TableExtended
GROUP BY GroupingKey
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.