एक है। अनिर्दिष्ट कुल
ANY
कहा जाता है जो मान्य सिंटैक्स नहीं है, लेकिन आपकी निष्पादन योजनाओं में प्रकट होना संभव है। हालांकि यह कोई प्रदर्शन लाभ प्रदान नहीं करता है।
निम्न तालिका और अनुक्रमणिका संरचना को मानते हुए
CREATE TABLE T
(
id int identity primary key,
[group] char(1)
)
CREATE NONCLUSTERED INDEX ix ON T([group])
INSERT INTO T
SELECT TOP 1000000 CHAR( 65 + ROW_NUMBER() OVER (ORDER BY @@SPID) % 3)
FROM sys.all_objects o1, sys.all_objects o2, sys.all_objects o3
मैंने नमूना डेटा के साथ भी पॉप्युलेट किया है जैसे कि प्रति समूह कई पंक्तियां हैं।
आपकी मूल क्वेरी
SELECT MAX(id),
[group]
FROM T
GROUP BY [group]
Table 'T'. Scan count 1, logical reads 1367
और योजना
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([Expr1003]=MAX([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
ANY
प्राप्त करने के लिए फिर से लिखा गया कुल...
;WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY [group] ORDER BY [group] ) AS RN
FROM T)
SELECT id,
[group]
FROM cte
WHERE RN=1
Table 'T'. Scan count 1, logical reads 1367
और योजना
|--Stream Aggregate(GROUP BY:([[T].[group]) DEFINE:([[T].[id]=ANY([[T].[id])))
|--Index Scan(OBJECT:([[T].[ix]), ORDERED FORWARD)
भले ही संभावित रूप से SQL सर्वर पहला मान मिलते ही समूह को संसाधित करना बंद कर सकता है और अगले पर छोड़ देता है जो ऐसा नहीं करता है। यह अभी भी सभी पंक्तियों को संसाधित करता है और तार्किक पठन समान हैं।
इस विशेष उदाहरण के लिए समूह में कई पंक्तियों के साथ एक अधिक कुशल संस्करण एक पुनरावर्ती CTE होगा।
WITH RecursiveCTE
AS (
SELECT TOP 1 id, [group]
FROM T
ORDER BY [group]
UNION ALL
SELECT R.id, R.[group]
FROM (
SELECT T.*,
rn = ROW_NUMBER() OVER (ORDER BY (SELECT 0))
FROM T
JOIN RecursiveCTE R
ON R.[group] < T.[group]
) R
WHERE R.rn = 1
)
SELECT *
FROM RecursiveCTE
OPTION (MAXRECURSION 0);
जो देता है
Table 'Worktable'. Scan count 2, logical reads 19
Table 'T'. Scan count 4, logical reads 12
तार्किक पठन बहुत कम है क्योंकि यह प्रति समूह पहली पंक्ति को पुनः प्राप्त करता है और फिर रिकॉर्ड के भार को पढ़ने के बजाय अगले समूह में खोजता है जो अंतिम परिणाम में योगदान नहीं करते हैं।