Oracle
 sql >> Base de données >  >> RDS >> Oracle

Fonctions RANK, DENSE_RANK et ROW_NUMBER dans Oracle

Les fonctions Oracle Analytic calculent une valeur agrégée basée sur un groupe de lignes appelé fenêtre qui détermine la plage de lignes utilisées pour effectuer les calculs pour la ligne actuelle. Voici les fonctions analytiques les plus utilisées.
– RANK, DENSE_RANK et ROW_NUMBER
– LAG et LEAD
– FIRST_VALUE et LAST_VALUE

Je discuterais des fonctions d'analyse RANK, DENSE_RANK et ROW_NUMBER. Elles sont de nature assez similaire et nous devons les utiliser en fonction des besoins. J'expliquerais également la différence entre elles

Voici la syntaxe générale

analytic_function([ arguments ]) OVER ([ query_partition_clause ] [ order_by_clause  ])

Fonction ROW_NUMBER dans Oracle

ROW_NUMBER attribue un numéro unique à chaque ligne de la même fenêtre dans la séquence ordonnée de lignes spécifiée par order_by_clause.

Commençons par créer des exemples de données

CREATE TABLE "DEPT"( "DEPTNO" NUMBER(2,0),"DNAME" VARCHAR2(14),"LOC" VARCHAR2(13),CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO"))CREATE TABLE " EMP"( "EMPNO" NUMBER(4,0),"ENAME" VARCHAR2(10),"JOB" VARCHAR2(9),"MGR" NUMBER(4,0),"HIREDATE" DATE,"SAL" NUMBER(7 ,2), "COMM" NUMBER (7,2), "DEPTNO" NUMBER (2,0), CONTRAINTE " PK_EMP " CLÉ PRIMAIRE (" EMPNO "), CONTRAINTE " FK_DEPTNO " CLÉ ÉTRANGÈRE (" DEPTNO ") RÉFÉRENCES " DEPT " ("DEPTNO") ENABLE);SQL> desc empName Null ? Type---- ---- -----EMPNO NOT NULL NUMBER(4)ENAME VARCHAR2(10)JOB VARCHAR2(9)MGR NUMBER(4)HIREDATE DATESAL NUMBER(7,2)COMM NUMBER(7,2) )DEPTNO NUMBER(2)SQL> desc deptName Null ? Type---- ----- ----DEPTNO NOT NULL NUMBER(2)DNAME VARCHAR2(14)LOC VARCHAR2(13)insert into DEPT values(10, 'ACCOUNTING', 'NEW YORK');insert into dept values(20, 'RESEARCH', 'DALLAS');insérer dans dept values(30, 'RESEARCH', 'DELHI');insérer dans dept values(40, 'RESEARCH', 'MUMBAI');commit;insérer dans valeurs emp( 7839, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 28573, null, 10 );insérer dans les valeurs emp( 7782, 'Clara ', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 0, null, 10 );insert into emp values( 7934, 'Blake', 'MANAGER', 7839 , to_date('1-5-2007','dd-mm-yyyy'), 0, null, 10 );insert into emp values( 7788, 'Scott', 'ANALYST', 7788, to_date('9-6 -2012','jj-mm-aaaa'), 30000, null, 20 );insérer dans les valeurs emp( 7902, 'Bill', 'ANALYST', 7832, to_date('9-6-2012','dd- mm-aaaa'), 30000, null, 20 );insérer dans les valeurs emp( 7876, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 11000 , null, 20 );insérer dans les valeurs emp( 7369, 'TPM1', 'ANALYST', 7566, to_date('9-6-2017',' jj-mm-aaaa'), 8000, null, 20 );insérer dans les valeurs emp( 7698, 'A1', 'ANALYST', 7788, to_date('9-6-2017','dd-mm-yyyy') , 28500, null, 30 );insérer dans les valeurs emp( 7499, 'A2', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 16000, null, 30 );insérer dans les valeurs emp( 7844, 'A3', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 15000, null, 30 );insérer dans les valeurs emp( 7654 , 'A4', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );insert into emp values( 7521, 'A5', 'ANALYST ', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );insert into emp values( 7900, 'A6', 'ANALYST', 77698, to_date(' 9-7-2017','dd-mm-yyyy'), 0, null, 30 );commit;
SQL> desc emp Nom Null ? Taper ----------------------------------------- -------- ------------------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER(2)SQL> select deptno ,count(*) from emp group by deptno; DEPTNO COUNT(*)---------- ---------- 30 6 20 4 10 3SQL> selectdeptno, ename, sal, row_number() over (partition by deptno order by sal) "numéro_ligne"fromemp;DEPTNO ENAME SAL numéro_ligne---------- ---------- ---------- ---------- 10 Clark 0 1 10 Miller 0 210 Allen 28573 320 Smith 8000 120 Adams 11000 220 Scott 30000 320 Ford 30000 430 James 9500 130 Martin 12500 230 Ward 12500 330 Turner 15000 430 Allen 16000 530 Blake 28500 6 13 Rows Sélectionnés. 

Fonction RANG dans Oracle

CLASSEMENT est presque identique à ROW_NUMBER mais les lignes avec des valeurs égales, avec dans la même fenêtre, pour lesquelles la clause order by est spécifiée reçoivent le même rang mais la ligne suivante reçoit RANK selon elle ROW_NUMBER.

SQL> selectdeptno, ename, sal, rank() over (partition by deptno order by sal) "RANK"fromemp;DEPTNO ENAME SAL RANK---------- -------- -- ---------- ---------- 10 CLARK 0 1 10 MILLER 0 210 allen 28573 320 SMITH 8000 120 ADAMS 11000 220 SCOTT 30000 320 FORD 30000 330 JAMES 9500 130 MARTIN 12500 230 WARD 12500 230 TURNER 15000 430 ALLEN 16000 530 BLAKE 28500 6 13 rangées sélectionnées.

Fonction Dense_rank dans Oracle

DENSE_RANK est presque identique au RANG, mais il ne laisse pas d'espace entre les lignes si une ou plusieurs valeurs sont identiques. Comme dans l'exemple suivant, TURNER à côté de WARD dans le même groupe reçoit DENSE_RANK 3.

SQL> selectdeptno, ename, sal, dense_rank() over (partition by deptno order by sal) "DENSE_RANK"fromemp;DEPTNO ENAME SAL DENSE_RANK---------- -------- -- ---------- ---------- 10 CLARK 0 1 10 MILLER 0 210 allen 28573 320 SMITH 8000 120 ADAMS 11000 220 SCOTT 30000 320 FORD 30000 330 JAMES 9500 130 MARTIN 12500 230 WARD 12500 230 TURNER 15000 330 ALLEN 16000 430 BLAKE 28500 5 13 rangées sélectionnées.

Nous pouvons également mettre les trois dans la requête unique

select deptno, ename, sal, row_number() over (partition by deptno order by sal) "row_number", rank() over (partition by deptno order by sal) "rank", dense_rank() over (partition by deptno order by sal) "rank", dense_rank() over (partition by deptno order by sal) ordre par sal) "dense_rank" de emp ; DEPTNO ENAME SAL row_number rank dense_rank---------- ---------- ---------- ---------- ---- ------ ---------- 10 CLARK 0 1 1 1 10 MILLER 0 2 1 1 10 allen 28573 3 3 2 20 SMITH 8000 1 1 1 20 ADAMS 11000 2 2 2 20 SCOTT 30000 3 3 3 20 FORD 30000 4 3 3 30 JAMES 9500 1 1 1 30 MARTIN 12500 2 2 2 30 WARD 12500 3 2 2 30 TURNER 15000 4 4 3 30 ALLEN 16000 5 5 4 30 BLAKE 28500 6 6 5 lignes sélectionnées 

Nous pouvons utiliser la fonction Row_number et RANK pour supprimer les lignes en double

delete from t where rowid IN ( select rid from (select rowid rid, row_number() over (partition by column_name order by rowid) rn from t) where rn <> 1);

Ces fonctions sont très utiles pour les requêtes top-N et bottom-N.

Le SQL ci-dessous peut être utilisé pour trouver le meilleur salaire dans chaque département

SQL> select * (selectdeptno, ename, sal, row_number() over (partition by deptno order by sal) "row_number"fromemp ) where row_number=1 ;

J'espère que vous aimez les explications sur RANK, DENSE_RANK et ROW_NUMBER comme les fonctions Oracle Analytic et comment nous pouvons les utiliser dans la requête pour analyser les données. Nous devons être très prudents lors de l'utilisation de ces fonctions dans les requêtes, sinon le résultat serait différent.

Articles connexes

Fonction LEAD dans Oracle
Fonctions analytiques dans Oracle
Questions d'entretien Oracle
Oracle Set Operators
Tutoriel Oracle Sql
Documentation Oracle Dense Rank