RANK()
関数とDENSE_RANK()
関数の違いは何ですか?次のemptbl
テーブルでn番目の給与を見つける方法は?
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
給与を調べたい場合はどうなりますか?
ランクはあなたの順序付けられたパーティション内のランキングをあなたに与えます。ネクタイには同じランクが割り当てられ、次のランクはスキップされます。したがって、ランク2のアイテムが3つある場合、リストの次のランクは5になります。
DENSE_RANKは再びあなたの順序付けられたパーティション内のランキングをあなたに与えます、しかしランクは連続しています。複数のアイテムを持つランクがある場合、ランクはスキップされません。
NULLについては、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.
この記事では、このトピックについて詳しく説明しています。 基本的に、そのように考えることができます。
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()
は同じ行番号を同じ値に属性付けし、 "穴"を残さない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
rank():レコードを行グループ内でランク付けするために使用されます。
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 |
+--------+------+-----------+
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()
は連続ランクを与えますが、ランクの衝突の場合にはrankはランクをスキップします。
RANK()関数とDENSE_RANK()関数の唯一の違いは、「tie」がある場合です。すなわち、セット内の複数の値が同じランキングを持つ場合。このような場合、RANK()はセット内の値に非連続の「ランク」を割り当て(タイがある場合は整数のランク値の間にギャップが生じます)、DENSE_RANK()は連続のランクをにセットします。設定します(したがって、tieの場合は整数のランク付け値の間にギャップはありません)。
例えば、集合{25、25、50、75、75、100}を考えてみましょう。そのようなセットでは、RANK()は{1、1、3、4、4、6}を返します(値2と5はスキップされます)が、DENSE_RANK()は{1,1,2,3、...を返します。 3,4}。
Rank()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