RANK () और DENSE_RANK () निर्धारक या गैर-नियतात्मक हैं?


27

आधिकारिक Microsoft BOL DENSE_RANK के अनुसार nondeterministic ( RANK () ) है। लेकिन इत्ज़िक बेन-गान द्वारा रैंकिंग फ़ंक्शंस के अनुसार ... RANK () और DENSE_RANK () फ़ंक्शंस हमेशा निर्धारक होते हैं "। कौन सही है?

मैंने अब तक क्या पाया है: Microsoft की परिभाषा "नियतात्मक कार्य हमेशा उसी परिणाम को वापस करते हैं जब भी उन्हें इनपुट मानों के एक विशिष्ट सेट के साथ बुलाया जाता है और डेटाबेस की समान स्थिति दी जाती है।"

तो सेट सिद्धांत तालिकाओं में कर्मचारी

Employee            Salary
Sue Right            1.00
Robin Page           1.00
Phil Factor          1.00

और कर्मचारी 2

Employee            Salary
Phil Factor          1.00
Sue Right            1.00
Robin Page           1.00

समान हैं। लेकिन रैंकिंग फ़ंक्शंस अलग मान लौटाते हैं:

    CREATE TABLE [dbo].[Employees](
    --[ID] [int] IDENTITY(1,1) NOT NULL,
    [Employee] [varchar](150) NOT NULL,
    [Salary] [smallmoney] NULL,
) ON [PRIMARY]

GO
CREATE TABLE [dbo].[Employees2](
    --[ID] [int] IDENTITY(1,1) NOT NULL,
    [Employee] [varchar](150) NOT NULL,
    [Salary] [smallmoney] NULL,
) ON [PRIMARY]

INSERT INTO [dbo].[Employees]
([Employee] ,[Salary])
VALUES
('Sue Right', 1)
, ('Robin Page', 1)
,('Phil Factor', 1 )
GO
INSERT INTO [dbo].[Employees2]
([Employee] ,[Salary])
VALUES
('Phil Factor', 1 )
,('Sue Right', 1)
,('Robin Page', 1)
GO
SELECT RANK() OVER ( ORDER BY Salary) AS [Rank]
, DENSE_RANK() OVER (ORDER BY Salary ) AS [Dense_rank]
, [Employee]
FROM
dbo.Employees

SELECT RANK() OVER ( ORDER BY Salary) AS [Rank]
, DENSE_RANK() OVER (ORDER BY Salary ) AS [Dense_rank]
, [Employee]
FROM
dbo.Employees2

SELECT NTILE(3) OVER ( ORDER BY SALARY )
, [Employee]
FROM
dbo.Employees

SELECT NTILE(3) OVER ( ORDER BY SALARY )
, [Employee]
FROM
dbo.Employees2

जवाबों:


23

आधिकारिक Microsoft BOL DENSE_RANK के अनुसार nondeterministic (RANK ()) है। लेकिन इत्ज़िक बेन-गान द्वारा रैंकिंग फ़ंक्शंस के अनुसार ... RANK () और DENSE_RANK () फ़ंक्शंस हमेशा निर्धारक होते हैं "। कौन सही है?

वे दोनों सही हैं, क्योंकि वे "नियतात्मक" शब्द के विभिन्न इंद्रियों का उपयोग कर रहे हैं।

SQL सर्वर ऑप्टिमाइज़र के दृष्टिकोण से, "नियतात्मक" का बहुत सटीक अर्थ है; एक अर्थ जो खिड़की और रैंकिंग कार्यों से पहले अस्तित्व में था उत्पाद में जोड़ा गया था। ऑप्टिमाइज़र के लिए, "निर्धारक" संपत्ति परिभाषित करती है कि क्या अनुकूलन के दौरान इसकी आंतरिक पेड़ संरचनाओं के भीतर एक फ़ंक्शन को स्वतंत्र रूप से दोहराया जा सकता है। यह गैर-नियतात्मक कार्य के लिए कानूनी नहीं है।

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

ROW_NUMBERसमारोह (परिभाषा के द्वारा!) अलग पंक्तियों के लिए अलग-अलग मान देता है, तो के लिए अनुकूलन प्रयोजनों यह गैर नियतात्मक है

यह वह अर्थ है जो BOL उपयोग कर रहा है।

इत्ज़िक समग्र रूप से परिणाम के निर्धारण के बारे में एक अलग बिंदु बना रहा है। एक ऑर्डर किए गए इनपुट सेट (उपयुक्त टाई-ब्रेकिंग के साथ) पर आउटपुट एक "निर्धारक" अनुक्रम है। यह एक मान्य अवलोकन है, लेकिन यह "नियतात्मक" गुणवत्ता नहीं है जो क्वेरी अनुकूलन के दौरान महत्वपूर्ण है।


10

NTILE()एक दिलचस्प मामला है; यह सॉर्ट करने के बाद लागू होता है (जो कि टाई के मामले में, SQL सर्वर के अपने उपकरणों पर छोड़ दिया जाता है, और यह आमतौर पर छँटाई प्रयोजनों के लिए सूचकांक के सबसे कुशल विकल्प द्वारा संचालित होता है)। आप एसक्यूएल सर्वर को यहां मनमानी पसंद करने के लिए मजबूर नहीं करके इस निर्धारक को बना सकते हैं - OVER()खंड में एक या एक से अधिक टाई-ब्रेकर जोड़ें :

OVER (ORDER BY Salary, Employee)

अनिवार्य रूप से आपको छंटाई को अद्वितीय बनाने की आवश्यकता है। यदि आपके पास एक ही नाम वाले कर्मचारी हैं, तो आपको एक अलग टाई-ब्रेकर कॉलम चुनना होगा या कॉलम जोड़ना जारी रखना चाहिए जब तक कि वास्तव में कोई संबंध न हो।

के लिए RANK()और DENSE_RANK(), संबंधों वास्तव में एक महत्वपूर्ण कारण यह है कि आप कर रहे हैं नहीं कर सकते विभिन्न मूल्यों मिलता है। परिणामों के क्रम के निर्धारण के साथ फ़ंक्शन के आउटपुट के निर्धारकवाद को भ्रमित न करने का प्रयास करें। यदि आपके प्रश्न नहीं हैं ORDER BY, तो इस बारे में निर्धारक क्या नहीं है?

1   1   Sue Right
1   1   Robin Page
1   1   Phil Factor

1   1   Phil Factor
1   1   Sue Right
1   1   Robin Page

RANK()और DENSE_RANK()दोनों ही मामलों में समान मानों को लागू किया, SQL सर्वर ने आपको एक अलग क्रम में परिणाम लौटा दिए। इसका समान आउटपुट से RANK()या DENSE_RANK()समान इनपुट की अपेक्षा करने से कोई लेना-देना नहीं है - यह सिर्फ SQL सर्वर (एक ORDER BYखंड को छोड़ कर ) को बताए जाने पर कुछ नियतकालिक आदेश मानने या अपेक्षा के बारे में है जिसे आप ऑर्डर के बारे में परवाह नहीं करते हैं परिणाम। # 3 यहां देखें:


7

वाक्य - विन्यास:

WindowFunction() OVER (PARTITION BY <some expressions>        -- partition list
                       ORDER BY <some other expressions>)     -- order list

दोनों कार्यों, RANK()और DENSE_RANK(), उनकी परिभाषाओं के अनुसार, जब तक OVERखंड में अभिव्यक्तियाँ स्वयं निर्धारित नहीं होती हैं तब तक वही परिणाम देने की गारंटी दी जाती है। और यही इत्ज़िक बेन-गन का मतलब अपने लेख में था। इन सूचियों में सबसे अधिक बार केवल शामिल तालिकाओं के स्तंभ हैं।

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

मेरा जंगली अनुमान यह है कि एसक्यूएल-सर्वर डेवलपर्स ने फैसला किया कि उन्हें हमेशा "गैर-नियतात्मक" के रूप में लागू करना आसान था, इसके बावजूद कि यह एक तरह से नियतात्मक कार्यों की उनकी परिभाषा के विपरीत है। इसलिए, उन्हें MSDN में गैर-नियतात्मक कहा जाता है क्योंकि वर्तमान कार्यान्वयन में, इंजन उन्हें हमेशा गैर-निर्धारक के रूप में मानता है।

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


मैं परिणाम सेट के आदेश पर टिप्पणी नहीं करूंगा, क्योंकि इसका नियतत्ववाद से कोई लेना-देना नहीं है, क्योंकि हारून बर्ट्रेंड ने अपने जवाब में स्पष्ट रूप से बताया है।

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