2009-09-23 21 views
63

में मुझे एक प्रश्न मिला जहां क्लॉज में Row_Number() फ़ंक्शन के साथ एक प्रश्न का उत्तर दिया गया। जब मैंने एक प्रश्न का प्रयास किया, तो मुझे निम्न त्रुटि मिल रही थी:SQL Row_Number() फ़ंक्शन कहां क्लॉज

"Msg 4108, Level 15, State 1, Line 1 Windowed functions can only appear in the SELECT or ORDER BY clauses."

यहां मैंने जो प्रश्न उठाया है, वह यहां है। अगर कोई जानता है कि इसे कैसे हल किया जाए, तो कृपया मुझे बताएं।

SELECT employee_id 
FROM V_EMPLOYEE 
WHERE row_number() OVER (ORDER BY employee_id) > 0 
ORDER BY Employee_ID 
+7

'ROW_NUMBER() ओवर (कर्मचारी_आईडी द्वारा आदेश)> 0' हमेशा 'TRUE' – Quassnoi

+1

हाँ का मूल्यांकन करेगा , ये सही है। मैं इस शर्त के बारे में चिंतित नहीं हूं, जिसे मैं किसी भी समय बदल सकता हूं। मैं चाहता हूं कि क्वेरी पहले काम करे, फिर 500 और 800 के बीच राउनंबर रखने की सोच ... धन्यवाद –

+1

@ जोसेफ: आप सीटीई का उपयोग करने से बचने की कोशिश क्यों कर रहे हैं? –

उत्तर

49
SELECT employee_id 
FROM (
     SELECT employee_id, ROW_NUMBER() OVER (ORDER BY employee_id) AS rn 
     FROM V_EMPLOYEE 
     ) q 
WHERE rn > 0 
ORDER BY 
     Employee_ID 

ध्यान दें कि यह फिल्टर बेमानी है: 1 से ROW_NUMBER() शुरू होता है और हमेशा 0 से अधिक है।

+0

उत्कृष्ट। इससे मुझे एक टन मदद मिली। धन्यवाद। –

+0

@Quassnoi धन्यवाद! जिज्ञासा: 'q' क्यों है? इसका क्या मतलब है? –

+1

@ DavideChicco.it: SQL सर्वर में, व्युत्पन्न तालिकाओं को उपनाम की आवश्यकता होती है (मुझे इसके बजाय 'AS q' लिखा जाना चाहिए था, लेकिन यह या तो काम करेगा)। – Quassnoi

69

इस समस्या को हल करने के लिए, अपने चयन कथन को सीटीई में लपेटें, और फिर आप सीटीई के खिलाफ पूछ सकते हैं और विंडो में फ़ंक्शन के परिणामों का उपयोग कहां से कर सकते हैं।

WITH MyCte AS 
(
    select employee_id, 
      RowNum = row_number() OVER (order by employee_id) 
    from  V_EMPLOYEE 
    ORDER BY Employee_ID 
) 
SELECT employee_id 
FROM MyCte 
WHERE RowNum > 0 
+4

मैं सीटीई से बचने की कोशिश कर रहा हूं। मैं जिस खराब मामले की तलाश में हूं, वह है। धन्यवाद –

+2

यदि आप सीटीई के बजाए सबक्वायरी का उपयोग करते हैं तो यह तेज़ी से चल सकता है। मैंने कुछ मामलों में 1.5 के कारक द्वारा बेहतर प्रदर्शन देखा है –

+0

क्या मैं उप क्वेरी – Xulfee

14

मुझे लगता है कि आप कुछ इस तरह हैं:

SELECT employee_id 
FROM (SELECT employee_id, row_number() 
     OVER (order by employee_id) AS 'rownumber' 
     FROM V_EMPLOYEE) TableExpressionsMustHaveAnAliasForDumbReasons 
WHERE rownumber > 0 
+3

उपरोक्त क्वेरी आपके लिए काम नहीं करती है, तो तालिका के लिए उपनाम बनाएं। दूसरी अंतिम पंक्ति को 'से V_EMPLOYEE) ए' के ​​रूप में संशोधित करें जो ए को उपनाम के रूप में जोड़ता है। –

3

CTE का उपयोग करना (एसक्यूएल सर्वर 2005+):

WITH employee_rows AS (
    SELECT t.employee_id, 
     ROW_NUMBER() OVER (ORDER BY t.employee_id) 'rownum' 
    FROM V_EMPLOYEE t) 
SELECT er.employee_id 
    FROM employee_rows er 
WHERE er.rownum > 1 

का उपयोग इनलाइन दृश्य/गैर CTE समतुल्य वैकल्पिक:

SELECT er.employee_id 
    FROM (SELECT t.employee_id, 
       ROW_NUMBER() OVER (ORDER BY t.employee_id) 'rownum' 
      FROM V_EMPLOYEE t) er 
WHERE er.rownum > 1 
+0

प्रदर्शन में कौन सा बेहतर है? सीटीई या सबक्वायरी का उपयोग करना? धन्यवाद –

+0

शैनन का जवाब देखें - उनके परीक्षण में वे बराबर हैं। –

+5

नहीं, यह तेज़ नहीं है। 'एसक्यूएल सर्वर' में, 'सीटीई' और इनलाइन विचार एक ही चीज हैं और समान प्रदर्शन करते हैं। जब 'सीटीई' में गैर-निर्धारक कार्यों का उपयोग किया जाता है, तो प्रत्येक कॉल पर इसका पुनर्मूल्यांकन किया जाता है। एक को 'सीटीई' के भौतिकरण को मजबूर करने के लिए गंदे चाल का उपयोग करना पड़ता है। इन लेखों को मेरे ब्लॉग में देखें: http: // explainextended।कॉम/200 9/07/28/एसक्यूएल-सर्वर-यादृच्छिक-रिकॉर्ड-avoiding-cte-reevaluation/http://explainextended.com/2009/05/28/generating-xml-in-subqueries/ – Quassnoi

5

रेक्सम पर टिप्पणियों के जवाब में जवाब, एक इनलाइन व्यू या सीटीई तेजी से होगा या नहीं, मैं तालिका 1 का उपयोग करने के लिए प्रश्नों को दोबारा बताता हूं, और हर कोई उपलब्ध था: sys.objects।

WITH object_rows AS (
    SELECT object_id, 
     ROW_NUMBER() OVER (ORDER BY object_id) RN 
    FROM sys.objects) 
SELECT object_id 
FROM object_rows 
WHERE RN > 1 

SELECT object_id 
FROM (SELECT object_id, 
     ROW_NUMBER() OVER (ORDER BY object_id) RN 
    FROM sys.objects) T 
WHERE RN > 1 

उत्पाद की क्वेरी योजना बिल्कुल वही थी। मैं सभी मामलों में उम्मीद करता हूं, क्वेरी ऑप्टिमाइज़र कम से कम सीटीई के इनलाइन व्यू या इसके विपरीत के साथ सरल प्रतिस्थापन में एक ही योजना के साथ आ जाएगा।

बेशक, यह देखने के लिए कि क्या कोई अंतर है या नहीं, अपने सिस्टम पर अपने स्वयं के प्रश्नों का प्रयास करें।

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

+0

Thx Shannon। आप SQL सर्वर का किस संस्करण का उपयोग कर रहे थे? –

+0

तो इसका मतलब है कि उस लिंक में प्रदान किया गया उत्तर गलत है? लेकिन, जिस व्यक्ति ने प्रश्न पोस्ट किया वह इस बात पर सहमत हो गया कि यह काम कर रहा है .. आश्चर्यजनक .. :-) –

+1

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

1

सवाल का ओपी के उत्तर के आधार पर: "विधि 2"

Please see this link. Its having a different solution, which looks working for the person who asked the question. I'm trying to figure out a solution like this.

Paginated query using sorting on different columns using ROW_NUMBER() OVER() in SQL Server 2005

~Joseph

"विधि 1" से जुड़ा हुआ सवाल से ओपी की क्वेरी की तरह है, और की तरह है चयनित उत्तर से क्वेरी। वास्तव में क्या चल रहा था यह देखने के लिए आपको इस answer में लिंक किए गए कोड को देखना था, क्योंकि चयनित उत्तर में कोड इसे काम करने के लिए संशोधित किया गया था।इस प्रयास करें:

DECLARE @YourTable table (RowID int not null primary key identity, Value1 int, Value2 int, value3 int) 
SET NOCOUNT ON 
INSERT INTO @YourTable VALUES (1,1,1) 
INSERT INTO @YourTable VALUES (1,1,2) 
INSERT INTO @YourTable VALUES (1,1,3) 
INSERT INTO @YourTable VALUES (1,2,1) 
INSERT INTO @YourTable VALUES (1,2,2) 
INSERT INTO @YourTable VALUES (1,2,3) 
INSERT INTO @YourTable VALUES (1,3,1) 
INSERT INTO @YourTable VALUES (1,3,2) 
INSERT INTO @YourTable VALUES (1,3,3) 
INSERT INTO @YourTable VALUES (2,1,1) 
INSERT INTO @YourTable VALUES (2,1,2) 
INSERT INTO @YourTable VALUES (2,1,3) 
INSERT INTO @YourTable VALUES (2,2,1) 
INSERT INTO @YourTable VALUES (2,2,2) 
INSERT INTO @YourTable VALUES (2,2,3) 
INSERT INTO @YourTable VALUES (2,3,1) 
INSERT INTO @YourTable VALUES (2,3,2) 
INSERT INTO @YourTable VALUES (2,3,3) 
INSERT INTO @YourTable VALUES (3,1,1) 
INSERT INTO @YourTable VALUES (3,1,2) 
INSERT INTO @YourTable VALUES (3,1,3) 
INSERT INTO @YourTable VALUES (3,2,1) 
INSERT INTO @YourTable VALUES (3,2,2) 
INSERT INTO @YourTable VALUES (3,2,3) 
INSERT INTO @YourTable VALUES (3,3,1) 
INSERT INTO @YourTable VALUES (3,3,2) 
INSERT INTO @YourTable VALUES (3,3,3) 
SET NOCOUNT OFF 

DECLARE @PageNumber  int 
DECLARE @PageSize  int 
DECLARE @SortBy   int 

SET @PageNumber=3 
SET @PageSize=5 
SET @SortBy=1 


--SELECT * FROM @YourTable 

--Method 1 
;WITH PaginatedYourTable AS (
SELECT 
    RowID,Value1,Value2,Value3 
     ,CASE @SortBy 
      WHEN 1 THEN ROW_NUMBER() OVER (ORDER BY Value1 ASC) 
      WHEN 2 THEN ROW_NUMBER() OVER (ORDER BY Value2 ASC) 
      WHEN 3 THEN ROW_NUMBER() OVER (ORDER BY Value3 ASC) 
      WHEN -1 THEN ROW_NUMBER() OVER (ORDER BY Value1 DESC) 
      WHEN -2 THEN ROW_NUMBER() OVER (ORDER BY Value2 DESC) 
      WHEN -3 THEN ROW_NUMBER() OVER (ORDER BY Value3 DESC) 
     END AS RowNumber 
    FROM @YourTable 
    --WHERE 
) 
SELECT 
    RowID,Value1,Value2,Value3,RowNumber 
     ,@PageNumber AS PageNumber, @PageSize AS PageSize, @SortBy AS SortBy 
    FROM PaginatedYourTable 
    WHERE RowNumber>=(@PageNumber-1)*@PageSize AND RowNumber<=(@PageNumber*@PageSize)-1 
    ORDER BY RowNumber 



-------------------------------------------- 
--Method 2 
;WITH PaginatedYourTable AS (
SELECT 
    RowID,Value1,Value2,Value3 
     ,ROW_NUMBER() OVER 
     (
      ORDER BY 
       CASE @SortBy 
        WHEN 1 THEN Value1 
        WHEN 2 THEN Value2 
        WHEN 3 THEN Value3 
       END ASC 
       ,CASE @SortBy 
        WHEN -1 THEN Value1 
        WHEN -2 THEN Value2 
        WHEN -3 THEN Value3 
       END DESC 
     ) RowNumber 
    FROM @YourTable 
    --WHERE more conditions here 
) 
SELECT 
    RowID,Value1,Value2,Value3,RowNumber 
     ,@PageNumber AS PageNumber, @PageSize AS PageSize, @SortBy AS SortBy 
    FROM PaginatedYourTable 
    WHERE 
     RowNumber>=(@PageNumber-1)*@PageSize AND RowNumber<=(@PageNumber*@PageSize)-1 
     --AND more conditions here 
    ORDER BY 
     CASE @SortBy 
      WHEN 1 THEN Value1 
      WHEN 2 THEN Value2 
      WHEN 3 THEN Value3 
     END ASC 
     ,CASE @SortBy 
      WHEN -1 THEN Value1 
      WHEN -2 THEN Value2 
      WHEN -3 THEN Value3 
     END DESC 

उत्पादन:

RowID Value1 Value2 Value3 RowNumber PageNumber PageSize SortBy 
------ ------ ------ ------ ---------- ----------- ----------- ----------- 
10  2  1  1  10   3   5   1 
11  2  1  2  11   3   5   1 
12  2  1  3  12   3   5   1 
13  2  2  1  13   3   5   1 
14  2  2  2  14   3   5   1 

(5 row(s) affected 

RowID Value1 Value2 Value3 RowNumber PageNumber PageSize SortBy 
------ ------ ------ ------ ---------- ----------- ----------- ----------- 
10  2  1  1  10   3   5   1 
11  2  1  2  11   3   5   1 
12  2  1  3  12   3   5   1 
13  2  2  1  13   3   5   1 
14  2  2  2  14   3   5   1 

(5 row(s) affected) 
+0

fyi, _SET SHOWPLAN_ALL ON_ विधि 1 का उपयोग करते समय 0.08424953 का कुल SubtreeCost था, जबकि विधि 2 0.02627153 पर था। विधि 2 तीन गुना बेहतर था। –

+0

क्षमा करें - विधि 2 इनलाइन व्यू या सीटीई है, सही? –

+0

@rexem, विधि 1 और 2 दोनों सीटीई का उपयोग करते हैं, जिस तरह से वे अंकन और क्रम पंक्तियों को अलग करते हैं। मुझे यकीन नहीं है कि यह वास्तविक प्रश्न इस प्रश्न से इतना अलग क्यों है कि ओपी लिंक (ओपी द्वारा इस प्रश्न के उत्तर में) से लिंक करता है, लेकिन मेरा उत्तर उस लिंक के आधार पर कामकाजी कोड बनाता है जिसे ओपी –

20
Select * from 
(
    Select ROW_NUMBER() OVER (order by Id) as 'Row_Number', * 
    from tbl_Contact_Us 
) as tbl 
Where tbl.Row_Number = 5 
+1

अच्छा उदाहरण! thx बहुत अधिक – richin

+1

महान उदाहरण के लिए धन्यवाद! इससे वास्तव में मदद मिली, क्योंकि मुझे पुराने SQL Server 2000 डेटाबेस पर काम करने के लिए इस कार्यक्षमता की आवश्यकता थी, जहां सीटीई मौजूद नहीं है। – StarPilot

-1
WITH MyCte AS 
(
    select 
     employee_id, 
     RowNum = row_number() OVER (order by employee_id) 
    from V_EMPLOYEE 
) 
SELECT employee_id 
FROM MyCte 
WHERE RowNum > 0 
ORDER BY employee_id 
-1

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

SELECT f0.* 
FROM FOO f0 
WHERE EXISTS 
    (SELECT f2.foo_id 
    FROM 
    (SELECT foo_id , 
     ROW_NUMBER() OVER(PARTITION BY F1.BAR_ID ORDER BY F1.AMOUNT) rk 
    FROM foo f1 
    )f2 
    WHERE f0.foo_id=f2.foo_id 
    AND rk   =2 -- your condition on row_number goes here 
);