ความแตกต่างระหว่างฟังก์ชัน RANK () และ DENSE_RANK () ใน oracle คืออะไร?


150

ความแตกต่างระหว่างRANK()และDENSE_RANK()ฟังก์ชั่นคืออะไร? วิธีการหาเงินเดือนที่ n ในemptblตารางต่อไปนี้?

DEPTNO  EMPNAME    SAL
------------------------------
10       rrr    10000.00
11       nnn    20000.00
11       mmm    5000.00
12       kkk    30000.00
10       fff    40000.00
10       ddd    40000.00
10       bbb    50000.00
10       ccc    50000.00

หากในตารางมีข้อมูลnullsจะเกิดอะไรขึ้นหากฉันต้องการค้นหาnthเงินเดือน

คำตอบ:


242

RANK ให้อันดับในพาร์ติชั่นที่คุณสั่ง ความสัมพันธ์ได้รับการจัดอันดับเดียวกันโดยการจัดอันดับถัดไปข้ามไป ดังนั้นหากคุณมี 3 รายการที่อันดับ 2 อันดับถัดไปที่ระบุไว้จะถูกจัดอันดับ 5

DENSE_RANK ให้อันดับคุณอีกครั้งภายในพาร์ติชั่นที่คุณสั่งซื้อ แต่อันดับนั้นต่อเนื่องกัน ไม่มีอันดับจะถูกข้ามถ้ามีอันดับที่มีหลายรายการ

สำหรับ nulls มันขึ้นอยู่กับข้อ ORDER BY นี่คือสคริปต์ทดสอบง่ายๆที่คุณสามารถเล่นเพื่อดูว่าเกิดอะไรขึ้น:

with q as (
select 10 deptno, 'rrr' empname, 10000.00 sal from dual union all
select 11, 'nnn', 20000.00 from dual union all
select 11, 'mmm', 5000.00 from dual union all
select 12, 'kkk', 30000 from dual union all
select 10, 'fff', 40000 from dual union all
select 10, 'ddd', 40000 from dual union all
select 10, 'bbb', 50000 from dual union all
select 10, 'xxx', null from dual union all
select 10, 'ccc', 50000 from dual)
select empname, deptno, sal
     , rank() over (partition by deptno order by sal nulls first) r
     , dense_rank() over (partition by deptno order by sal nulls first) dr1
     , dense_rank() over (partition by deptno order by sal nulls last) dr2
 from q; 

EMP     DEPTNO        SAL          R        DR1        DR2
--- ---------- ---------- ---------- ---------- ----------
xxx         10                     1          1          4
rrr         10      10000          2          2          1
fff         10      40000          3          3          2
ddd         10      40000          3          3          2
ccc         10      50000          5          4          3
bbb         10      50000          5          4          3
mmm         11       5000          1          1          1
nnn         11      20000          2          2          2
kkk         12      30000          1          1          1

9 rows selected.

นี่คือลิงก์ไปยังคำอธิบายที่ดีและตัวอย่างบางส่วน


14
ความคิดที่ดีมากที่จะใช้การเลือกสหภาพทั้งหมดจากคู่เพื่อสร้างข้อมูลตัวอย่างโดยไม่ต้องสร้างตารางใด ๆ
Jean-Christophe Blanchard

@ Jean-ChristopheBlanchard แม้ว่าคุณจะสามารถใช้valuesประโยคได้ง่ายๆ
Wildcard

1
@ Wildcard ใน PG ใช่ ใน Oracle, ไม่มี อย่างน้อยก็ไม่เท่ากับ 11 ฉันยังไม่พบ 12 ในการผลิต
jpmc26

ลบfrom dualเพื่อสร้างข้อมูลนี้ใน Redshift
Gaurav

4
อีวานอันดับทำให้ฉันมีความคิดที่ฉันเป็นญาติกับทุกคนที่อยู่ข้างหน้าของฉัน DENSE_RANK บอกอันดับที่แน่นอนให้ฉัน ฉันอาจมีเงินเดือนสูงสุดเป็นอันดับสอง แต่อาจมี 100 คนข้างหน้าของฉัน อันไหนดีกว่าขึ้นอยู่กับคำถามที่ฉันตอบ
DCookie

93

บทความนี้อธิบายไว้อย่างชัดเจน เป็นหลักคุณสามารถดูได้เช่น:

CREATE TABLE t AS
SELECT 'a' v FROM dual UNION ALL
SELECT 'a'   FROM dual UNION ALL
SELECT 'a'   FROM dual UNION ALL
SELECT 'b'   FROM dual UNION ALL
SELECT 'c'   FROM dual UNION ALL
SELECT 'c'   FROM dual UNION ALL
SELECT 'd'   FROM dual UNION ALL
SELECT 'e'   FROM dual;

SELECT
  v,
  ROW_NUMBER() OVER (ORDER BY v) row_number,
  RANK()       OVER (ORDER BY v) rank,
  DENSE_RANK() OVER (ORDER BY v) dense_rank
FROM t
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 |
+---+------------+------+------------+

ในคำ

  • ROW_NUMBER() คุณลักษณะค่าที่ไม่ซ้ำกับแต่ละแถว
  • RANK() แอตทริบิวต์หมายเลขแถวเดียวกันเป็นค่าเดียวกันโดยปล่อย "หลุม"
  • DENSE_RANK() แอตทริบิวต์หมายเลขแถวเดียวกันเป็นค่าเดียวกันโดยไม่ทิ้ง "หลุม"

ข้อผิดพลาด: ข้อผิดพลาดของ SQL: ORA-00923: ไม่พบคำหลักจากที่ที่คาดไว้
zloctb

9
SELECT empno,
       deptno,
       sal,
       RANK() OVER (PARTITION BY deptno ORDER BY sal) "rank"
FROM   emp;

     EMPNO     DEPTNO        SAL       rank
---------- ---------- ---------- ----------
      7934         10       1300          1
      7782         10       2450          2
      7839         10       5000          3
      7369         20        800          1
      7876         20       1100          2
      7566         20       2975          3
      7788         20       3000          4
      7902         20       3000          4
      7900         30        950          1
      7654         30       1250          2
      7521         30       1250          2
      7844         30       1500          4
      7499         30       1600          5
      7698         30       2850          6


SELECT empno,
       deptno,
       sal,
       DENSE_RANK() OVER (PARTITION BY deptno ORDER BY sal) "rank"
FROM   emp;

     EMPNO     DEPTNO        SAL       rank
---------- ---------- ---------- ----------
      7934         10       1300          1
      7782         10       2450          2
      7839         10       5000          3
      7369         20        800          1
      7876         20       1100          2
      7566         20       2975          3
      7788         20       3000          4
      7902         20       3000          4
      7900         30        950          1
      7654         30       1250          2
      7521         30       1250          2
      7844         30       1500          3
      7499         30       1600          4
      7698         30       2850          5

8

อันดับ () : มันถูกใช้เพื่อจัดอันดับระเบียนภายในกลุ่มของแถว

dense_rank () : ฟังก์ชั่น DENSE_RANK ทำหน้าที่เหมือนฟังก์ชั่น RANK ยกเว้นว่าจะกำหนดอันดับที่ต่อเนื่องกัน

คำค้นหา -

select 
    ENAME,SAL,RANK() over (order by SAL) RANK
from 
    EMP;

ผลผลิต -

+--------+------+------+
| ENAME  | SAL  | RANK |
+--------+------+------+
| SMITH  |  800 |    1 |
| JAMES  |  950 |    2 |
| ADAMS  | 1100 |    3 |
| MARTIN | 1250 |    4 |
| WARD   | 1250 |    4 |
| TURNER | 1500 |    6 |
+--------+------+------+

คำค้นหา -

select 
    ENAME,SAL,dense_rank() over (order by SAL) DEN_RANK
from 
    EMP;

ผลผลิต -

+--------+------+-----------+
| ENAME  | SAL  |  DEN_RANK |
+--------+------+-----------+
| SMITH  |  800 |         1 |
| JAMES  |  950 |         2 |
| ADAMS  | 1100 |         3 |
| MARTIN | 1250 |         4 |
| WARD   | 1250 |         4 |
| TURNER | 1500 |         5 |
+--------+------+-----------+

2
select empno
       ,salary
       ,row_number() over(order by salary desc) as Serial
       ,Rank() over(order by salary desc) as rank
       ,dense_rank() over(order by salary desc) as denseRank
from emp ;

Row_number() -> ใช้สำหรับสร้างหมายเลขซีเรียล

Dense_rank() จะให้อันดับอย่างต่อเนื่อง แต่อันดับจะข้ามอันดับในกรณีที่มีการปะทะกันของอันดับ


2

ข้อแตกต่างระหว่างฟังก์ชั่น RANK () และ DENSE_RANK () คือในกรณีที่มี“ tie”; กล่าวคือในกรณีที่ค่าหลายค่าในชุดมีอันดับเดียวกัน ในกรณีเช่นนี้ RANK () จะกำหนด“ อันดับ” ที่ไม่ต่อเนื่องให้กับค่าในชุด (ส่งผลให้เกิดช่องว่างระหว่างค่าการจัดอันดับจำนวนเต็มเมื่อมีการเสมอกัน) ในขณะที่ DENSE_RANK () จะกำหนดอันดับต่อเนื่องให้กับค่าใน set (ดังนั้นจะไม่มีช่องว่างระหว่างค่าการจัดอันดับจำนวนเต็มในกรณีของการผูก)

ตัวอย่างเช่นพิจารณาชุด {25, 25, 50, 75, 75, 100} สำหรับชุดดังกล่าว RANK () จะส่งกลับ {1, 1, 3, 4, 4, 6} (โปรดทราบว่าค่าที่ 2 และ 5 ถูกข้ามไป) ในขณะที่ DENSE_RANK () จะส่งกลับ {1,1,2,3 3,4}


1

อันดับ () ฟังก์ชัน SQL สร้างอันดับของข้อมูลภายในชุดของค่าที่เรียงลำดับ แต่อันดับถัดไปหลังจากอันดับก่อนหน้าคือ row_number ของแถวนั้น ในทางกลับกันฟังก์ชัน Dense_Rank () SQL จะสร้างหมายเลขถัดไปแทนที่จะสร้าง row_number ด้านล่างเป็นตัวอย่าง SQL ซึ่งจะอธิบายแนวคิด:

Select ROW_NUMBER() over (order by Salary) as RowNum, Salary, 
RANK() over (order by Salary) as Rnk, 
DENSE_RANK() over (order by Salary) as DenseRnk from (
Select 1000 as Salary union all
Select 1000 as Salary union all
Select 1000 as Salary union all
Select 2000 as Salary union all
Select 3000 as Salary union all
Select 3000 as Salary union all
Select 8000 as Salary union all
Select 9000 as Salary) A

มันจะสร้างผลลัพธ์ต่อไปนี้:

----------------------------
RowNum  Salary  Rnk DenseRnk
----------------------------
1       1000    1   1
2       1000    1   1
3       1000    1   1
4       2000    4   2
5       3000    5   3
6       3000    5   3
7       8000    7   4
8       9000    8   5

0

อันดับและหนาแน่นอันดับให้อันดับในชุดข้อมูลที่แบ่งพาร์ติชัน

อันดับ (): มันไม่ได้ให้เลขจำนวนเต็มต่อเนื่องกัน

Dense_rank (): มันให้หมายเลขจำนวนเต็มต่อเนื่องกัน

ป้อนคำอธิบายรูปภาพที่นี่

ในภาพด้านบนอันดับของ 1,0008 zip คือ 2 โดย dense_rank () function และ 24 by rank () ฟังก์ชันตามที่พิจารณา row_number


0

Rank(), Dense_rank(), row_number() ทั้งหมดเหล่านี้เป็นฟังก์ชั่นหน้าต่างซึ่งหมายความว่าพวกเขาทำหน้าที่เป็นหน้าต่างผ่านชุดคำสั่งอินพุทบางชุดในตอนแรก หน้าต่างเหล่านี้มีฟังก์ชั่นการใช้งานที่แตกต่างกันตามความต้องการ นี่คือด้านบน 3:

row_number()

เริ่มต้นด้วยrow_number()รูปแบบพื้นฐานของฟังก์ชั่นหน้าต่างที่เกี่ยวข้องเหล่านี้ row_number()เป็นชื่อแนะนำให้ตัวเลขที่ไม่ซ้ำกับชุดของแถวที่มีการใช้ คล้ายกับการให้หมายเลขซีเรียลแก่แต่ละแถว

Rank()

โค่นล้มของอาจกล่าวได้ว่าเป็นrow_number() rank()Rank () ใช้เพื่อให้หมายเลขอนุกรมเดียวกันกับแถวชุดที่ได้รับคำสั่งซึ่งซ้ำกัน แต่ก็ยังคงทำให้การนับมีความคล้ายคลึงกับrow_number()สำหรับทุก ๆ คนหลังจากซ้ำกันอันดับ () หมายถึงจากด้านล่างเช่น สำหรับ data 2 row_number () = rank () หมายถึงทั้งคู่ต่างกันในรูปแบบของการทำซ้ำ

Data row_number() rank() dense_rank() 
    1         1                    1       1
    1         2                    1       1
    1         3                    1       1
    2         4                    4       2

สุดท้าย

Dense_rank () เป็นรุ่นเพิ่มเติมของ rank () เป็นชื่อที่แนะนำให้หนาแน่นเพราะอย่างที่คุณเห็นจากตัวอย่างอันดับ () = dense_rank () สำหรับข้อมูลทั้งหมด 1 แต่ข้อมูล 2 นั้นแตกต่างกันในรูปแบบที่มัน ต้องเรียงลำดับของอันดับ () จากอันดับก่อนหน้า () ไม่ใช่ข้อมูลจริง


0

ข้อแตกต่างระหว่างฟังก์ชั่น RANK () และ DENSE_RANK () คือในกรณีที่มี“ tie”; กล่าวคือในกรณีที่ค่าหลายค่าในชุดมีอันดับเดียวกัน ในกรณีเช่นนี้ RANK () จะกำหนด“ อันดับ” ที่ไม่ต่อเนื่องให้กับค่าในชุด (ส่งผลให้เกิดช่องว่างระหว่างค่าการจัดอันดับจำนวนเต็มเมื่อมีการเสมอกัน) ในขณะที่ DENSE_RANK () จะกำหนดอันดับต่อเนื่องให้กับค่าใน set (ดังนั้นจะไม่มีช่องว่างระหว่างค่าการจัดอันดับจำนวนเต็มในกรณีของการผูก)

ตัวอย่างเช่นพิจารณาชุด {30, 30, 50, 75, 75, 100} สำหรับชุดดังกล่าว RANK () จะส่งกลับ {1, 1, 3, 4, 4, 6} (โปรดทราบว่าค่าที่ 2 และ 5 ถูกข้ามไป) ในขณะที่ DENSE_RANK () จะส่งกลับ {1,1,2,3 3,4}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.