2012-11-14 10 views
6

में एक स्केलर फ़ंक्शन को कई बार कॉल करने से बचें UPDATE कथन को संशोधित करने का कोई तरीका है ताकि स्केलर फ़ंक्शन को केवल एक बार बुलाया जाए, दो बार नहीं?अद्यतन दिनांक

UPDATE a 
    SET SomeField = b.SomeField 
    FROM TableA AS a 
    JOIN TableB b ON b.Link = a.Link 
    WHERE b.CostMin <= @Cost * dbo.OneScalarFunction(@CurrencyFrom, b.Currency) 
     AND b.CostMax >= @Cost * dbo.OneScalarFunction(@CurrencyFrom, b.Currency) 

पी.एस.BETWEEN ऑपरेटर का उपयोग करने में मदद नहीं करता है - SQL सर्वर स्केलर फ़ंक्शन को दो बार वैसे भी कॉल करता है।

उत्तर

5

इस बार काफी अधिक performant है, लेकिन एक इनलाइन तालिका महत्वपूर्ण कार्य करने के लिए अदिश समारोह को बदलने की आवश्यकता है।

UPDATE 
    a 
SET 
    SomeField = b.SomeField 
FROM 
    TableA AS a 
CROSS APPLY 
    dbo.oneInlineTableValuedFunction(@CurrencyFrom, e.Currency) AS ITVF 
INNER JOIN 
    TableB b 
    ON b.Link = a.Link 
WHERE 
     b.CostMin <= @Cost * ITVF.exchangeRate 
    AND b.CostMax >= @Cost * ITVF.exchangeRate 

हालांकि तालिका महत्वपूर्ण कार्यों टेबल लौटने के लिए, आप एक क्षेत्र के साथ सिर्फ एक पंक्ति retun चुन सकते हैं। तो फिर तुम यह एक अदिश समारोह के रूप में प्रभावी ढंग से उपयोग कर रहे हैं - लेकिन, आप कैसे एसक्यूएल सर्वर क्वेरी ऊपर अनुकूलन कर सकते हैं के सभी लाभ प्राप्त ...
- TVF इनलाइन (और नहीं बहु बयान)
है

CREATE FUNCTION dbo.oneInlineTableValuedFunction (
         @currencyFrom VARCHAR(32), 
         @currencyTo  VARCHAR(32) 
) 
RETURNS TABLE 
AS 
RETURN (
    SELECT 
    exchangeRate 
    FROM 
    dbo.someTable 
    WHERE 
     currencyFrom = @currencyFrom 
    AND currencyTo = @currencyTo 
) 
: - परिणाम प्रदर्शन dramatiaclly अदिश कार्यों


उदाहरण इनलाइन तालिका मूल्य समारोह से बेहतर है - TVF क्वेरी
में बाहर का विस्तार हो जाता है

जानबूझ कर इस बारे में तुच्छ

एक उदाहरण पोस्ट: scalar-functions-inlining-and-performance

आप INLINE CROSS APPLY SCALAR FUNCTION PERFORMANCE के लिए वेब खोज के तो मुझे यकीन है कि आप और भी बहुत कुछ मिल जाएगा।

+0

धन्यवाद। ऐसा लगता है कि तालिका-मूल्यवान कार्यों के पक्ष में स्केलर कार्यों को छोड़ने के अलावा कोई और विकल्प नहीं है। – 10p

+0

@ 10p - वे * पूरे डेटा-सेट पर लागू होने पर बड़े पैमाने पर अधिक कुशल होते हैं। – MatBailie

5

ऑपरेटर के साथ प्रयास करें।

WHERE functionCall(..) BETWEEN minValue AND maxValue 

http://www.w3schools.com/sql/sql_between.asp

+1

अच्छा विचार। हालांकि अभ्यास में यह '<=' and '> =' तक विस्तारित हो सकता है। –

+0

मैं परीक्षण करूंगा कि इसे इस मामले में दो बार नहीं कहा जाता है, धन्यवाद – 10p

+0

SQL सर्वर स्केलर फ़ंक्शन को दो बार कॉल करता है, मुझे लगता है कि यह सिर्फ एक अलग संकेत है, इसलिए यह सुझाव वास्तव में समस्या को हल नहीं करता है – 10p

3

आप (नीचे के रूप में) के बीच का उपयोग कर की कोशिश कर सकते डेटाबेस के रूप में> = यह निष्पादित करने के लिए इस बाहर विभाजित हो सकता है, हालांकि आप यह परीक्षण करने के लिए के रूप में मैं एक चुपके संदेह मिल गया है आवश्यकता होगी और < = वैसे भी ..

UPDATE a 
    SET SomeField = b.SomeField 
    FROM TableA AS a 
    JOIN TableB b ON b.Link = a.Link 
    WHERE @Cost * dbo.OneScalarFunction(@CurrencyFrom, e.Currency) BETWEEN b.CostMin AND b.CostMax 
+0

मैंने आपके ऊपर उठाया समाधान लेकिन उपयोगकर्ता 1660584 पहले – 10p

+0

था आप सही थे - SQL सर्वर इसे दो बार निष्पादित करता है – 10p

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