SQL RANK () बनाम ROW_NUMBER ()


189

मैं इन दोनों के बीच के मतभेदों को लेकर उलझन में हूं। निम्न एसक्यूएल चलाने से मुझे दो पहचान परिणाम सेट मिलते हैं। क्या कोई मतभेद की व्याख्या कर सकता है?

SELECT ID, [Description], RANK()       OVER(PARTITION BY StyleID ORDER BY ID) as 'Rank'      FROM SubStyle
SELECT ID, [Description], ROW_NUMBER() OVER(PARTITION BY StyleID ORDER BY ID) as 'RowNumber' FROM SubStyle

जवाबों:


221

ROW_NUMBER: 1. के साथ शुरू होने वाली प्रत्येक पंक्ति के लिए एक अद्वितीय संख्या देता है। उन पंक्तियों के लिए जिनमें डुप्लिकेट मान हैं, संख्याएँ मनमाने ढंग से असाइन की जाती हैं।

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


324

आप केवल उस अंतर को देखेंगे यदि आपके पास किसी विशेष ऑर्डरिंग मूल्य के लिए विभाजन के भीतर संबंध हैं।

RANKऔर DENSE_RANKइस मामले में नियतात्मक हैं, आदेश देने और विभाजन करने वाले दोनों स्तंभों के लिए समान मान वाली सभी पंक्तियाँ एक समान परिणाम के साथ समाप्त हो ROW_NUMBERजाएंगी , जबकि मनमाने ढंग से (गैर निर्धारक रूप से) बंधी हुई पंक्तियों को एक वृद्धि परिणाम प्रदान करेंगे।

उदाहरण: (सभी पंक्तियों में समान StyleIDहैं और एक ही विभाजन में हैं और उस विभाजन के भीतर पहली 3 पंक्तियाँ तब बाँधी जाती हैं जब आदेश दिया जाता है ID)

WITH T(StyleID, ID)
     AS (SELECT 1,1 UNION ALL
         SELECT 1,1 UNION ALL
         SELECT 1,1 UNION ALL
         SELECT 1,2)
SELECT *,
       RANK() OVER(PARTITION BY StyleID ORDER BY ID)       AS 'RANK',
       ROW_NUMBER() OVER(PARTITION BY StyleID ORDER BY ID) AS 'ROW_NUMBER',
       DENSE_RANK() OVER(PARTITION BY StyleID ORDER BY ID) AS 'DENSE_RANK'
FROM   T  

रिटर्न

StyleID     ID       RANK      ROW_NUMBER      DENSE_RANK
----------- -------- --------- --------------- ----------
1           1        1         1               1
1           1        1         2               1
1           1        1         3               1
1           2        4         4               2

आप देख सकते हैं कि तीन समान पंक्तियों के लिए ROW_NUMBERवेतन वृद्धि, RANKमूल्य समान रहता है फिर यह छलांग लगाता है 4DENSE_RANKतीनों पंक्तियों को समान रैंक भी प्रदान करता है लेकिन फिर अगले अलग मूल्य को 2 का मान दिया जाता है।


26
ग्रेट! ... DENSE_RANK
संदीप थॉमस

7
एक महान उदाहरण के लिए धन्यवाद। मुझे यह महसूस करने में मदद की कि मैं RANK () फ़ंक्शन का गलत उपयोग कर रहा हूं जब ROW_NUMBER () बहुत अधिक उपयुक्त होगा।
एल्स पोटोकनिक हाहोनिना

2
गंभीरता से, यह कमाल है।
मैट फेलजानी

35

इस लेख के बीच एक दिलचस्प संबंध पर चर्चा की ROW_NUMBER()औरDENSE_RANK() ( RANK()समारोह विशेष रूप से इलाज नहीं है)। जब आपको ROW_NUMBER()किसी SELECT DISTINCTकथन पर जनरेट करने की आवश्यकता होती है , तो वे कीवर्ड द्वारा हटाए जाने से पहलेROW_NUMBER() अलग-अलग मान उत्पन्न करेंगे । जैसे यह प्रश्नDISTINCT

SELECT DISTINCT
  v, 
  ROW_NUMBER() OVER (ORDER BY v) row_number
FROM t
ORDER BY v, row_number

... इस परिणाम का उत्पादन कर सकते हैं ( DISTINCTकोई प्रभाव नहीं है):

+---+------------+
| V | ROW_NUMBER |
+---+------------+
| a |          1 |
| a |          2 |
| a |          3 |
| b |          4 |
| c |          5 |
| c |          6 |
| d |          7 |
| e |          8 |
+---+------------+

जबकि यह प्रश्न:

SELECT DISTINCT
  v, 
  DENSE_RANK() OVER (ORDER BY v) row_number
FROM t
ORDER BY v, row_number

... इस मामले में आप जो चाहते हैं वह पैदा करता है:

+---+------------+
| V | ROW_NUMBER |
+---+------------+
| a |          1 |
| b |          2 |
| c |          3 |
| d |          4 |
| e |          5 |
+---+------------+

ध्यान दें कि ORDER BYके खंड DENSE_RANK()समारोह से सभी स्तंभों की आवश्यकता होगी SELECT DISTINCTठीक से काम करने के लिए खंड।

इसका कारण यह है कि तार्किक रूप से, विंडो फ़ंक्शन की गणना DISTINCTलागू होने से पहले की जाती है

तुलना में सभी तीन कार्य

PostgreSQL / Sybase / SQL मानक सिंटैक्स ( WINDOWक्लॉज) का उपयोग करना :

SELECT
  v,
  ROW_NUMBER() OVER (window) row_number,
  RANK()       OVER (window) rank,
  DENSE_RANK() OVER (window) dense_rank
FROM t
WINDOW window AS (ORDER BY v)
ORDER BY v

... आपको मिलेगा:

+---+------------+------+------------+
| V | ROW_NUMBER | RANK | DENSE_RANK |
+---+------------+------+------------+
| a |          1 |    1 |          1 |
| a |          2 |    1 |          1 |
| a |          3 |    1 |          1 |
| b |          4 |    4 |          2 |
| c |          5 |    5 |          3 |
| c |          6 |    5 |          3 |
| d |          7 |    7 |          4 |
| e |          8 |    8 |          5 |
+---+------------+------+------------+

1
ROW_NUMBER और DENSE_RANK दोनों अलग-अलग लागू होने से पहले मूल्यों का उत्पादन करते हैं। वास्तव में DISTINCT लागू होने से पहले सभी रैंकिंग फ़ंक्शन या कोई फ़ंक्शन परिणाम उत्पन्न करता है।
थानैसिस आयोनिडिस

1
@ थनैसीसोआनिडीस: बिल्कुल। मैंने एक ब्लॉग पोस्ट के लिंक के साथ अपना जवाब अपडेट किया है, जहाँ मैंने SQL संचालन
लुकास ईडर

3

बहुत थोड़ा:

पंक्ति की रैंक एक से अधिक रैंक है जो प्रश्न में पंक्ति से पहले आती है।

रो_नंबर पंक्तियों की विशिष्ट रैंक है, जो रैंकिंग में कोई अंतर नहीं है।

http://www.bidn.com/blogs/marcoadf/bidn-blog/379/ranking-functions-row_number-vs-rank-vs-dense_rank-vs-ntile


आह, मुझे लगता है कि यह वही है जो मैं याद कर रहा था -> रो_नंबर पंक्तियों की विशिष्ट रैंक है, रैंकिंग में किसी भी अंतराल के बिना।
डॉटनेट हॉबीएस्ट

1

विभाजन खंड के बिना सरल क्वेरी:

select 
    sal, 
    RANK() over(order by sal desc) as Rank,
    DENSE_RANK() over(order by sal desc) as DenseRank,
    ROW_NUMBER() over(order by sal desc) as RowNumber
from employee 

आउटपुट:

    --------|-------|-----------|----------
    sal     |Rank   |DenseRank  |RowNumber
    --------|-------|-----------|----------
    5000    |1      |1          |1
    3000    |2      |2          |2
    3000    |2      |2          |3
    2975    |4      |3          |4
    2850    |5      |4          |5
    --------|-------|-----------|----------

0

इस उदाहरण को देखें।

CREATE TABLE [dbo].#TestTable(
    [id] [int] NOT NULL,
    [create_date] [date] NOT NULL,
    [info1] [varchar](50) NOT NULL,
    [info2] [varchar](50) NOT NULL,
)

कुछ डेटा डालें

INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (1, '1/1/09', 'Blue', 'Green')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (1, '1/2/09', 'Red', 'Yellow')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (1, '1/3/09', 'Orange', 'Purple')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (2, '1/1/09', 'Yellow', 'Blue')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (2, '1/5/09', 'Blue', 'Orange')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (3, '1/2/09', 'Green', 'Purple')
INSERT INTO dbo.#TestTable (id, create_date, info1, info2)
VALUES (3, '1/8/09', 'Red', 'Blue')

1 के लिए समान मान दोहराएं

INSERT INTO dbo। # टेस्टटेबल (id, create_date, info1, info2) VALUES (1, '1/1/09', 'Blue', 'Green')

सब देखो

SELECT * FROM #TestTable

अपने परिणाम देखें

SELECT Id,
    create_date,
    info1,
    info2,
    ROW_NUMBER() OVER (PARTITION BY Id ORDER BY create_date DESC) AS RowId,
    RANK() OVER(PARTITION BY Id ORDER BY create_date DESC)    AS [RANK]
FROM #TestTable

अलग को समझने की जरूरत है


-1

RANK का उपयोग करते समय भी, PARTITION में ORDER BY पर ध्यान दें (Standard AdventureWorks db का उपयोग किया जाता है)।

1। SalesOrderID, as1। SalesOrderDetailID, RANK () OVER (PARTITION BY as1.SalesOrderID ORDER BY as1.SalesOrderID) रैंकोक्वल, RANK () OVER (PARTITION BY as1.SalesOrderDetailID) का चयन करें। SalesOrderId = 43659 SalesOrderDetailId द्वारा आदेश;

परिणाम देता है:

SalesOrderID SalesOrderDetailID rank_same_as_partition rank_salesorderdetailid
43,659 1 1 1
43,659 2 1 2
43,659 3 1 से 3
43,659 4 1 से 4
43,659 5 1 5
43,659 6 1 6
43,659 7 1 से 7
43,659 8 1 8
43,659 9 1 9
43,659 10 1 10
43,659 11 1 11
43,659 12 १ १२

लेकिन अगर ऑर्डर को बदलकर (ऑर्डरक्यूटी का उपयोग करें:

As1.SalesOrderID, as1.OrderQty, RANK () OVER (PARTITION BY as1.SalesOrderID ORDER BY as1.SalesOrderID) रेंकऑनक्वाल, RANK () OVER (PARTITION BY as1.SalesOrderID ORDER BY1OrderQO) के रूप में चयन करें। SalesOrderId = 43659 आदेश द्वारा आदेश;

देता है:

SalesOrderID OrderQty rank_salesorderid rank_orderqty
43,659 1 1 1
43,659 1 1 1
43,659 1 1 1
43,659 1 1 1
43,659 1 1 1
43,659 1 1 1
43,659 2 1 7
43,659 2 1 7
43,659 3 1 9
43,659 3 1 9
43,659 4 1 11
43,659 6 १ १२

ध्यान दें कि जब हम ORDER BY में OrderQty (सबसे दाहिने कॉलम दूसरी तालिका) का उपयोग करते हैं तो रैंक कैसे बदल जाता है और जब हम ORDER BY में SalesOrderDetailID (सबसे दाएं स्तंभ प्रथम तालिका) का उपयोग करते हैं तो यह कैसे बदल जाता है।


-1

मैंने रैंक के साथ कुछ भी नहीं किया है, लेकिन मैंने आज इसे row_number () के साथ खोजा।

select item, name, sold, row_number() over(partition by item order by sold) as row from table_name

यह कुछ दोहराए जाने वाले पंक्ति संख्याओं के परिणामस्वरूप होगा क्योंकि मेरे मामले में प्रत्येक नाम सभी आइटम रखता है। प्रत्येक आइटम का ऑर्डर दिया जाएगा कि कितने बेचे गए थे।

+--------+------+-----+----+
|glasses |store1|  30 | 1  |
|glasses |store2|  35 | 2  |
|glasses |store3|  40 | 3  |
|shoes   |store2|  10 | 1  |
|shoes   |store1|  20 | 2  |
|shoes   |store3|  22 | 3  |
+--------+------+-----+----+
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.