Oracle
 sql >> Database >  >> RDS >> Oracle

Funzioni RANK, DENSE_RANK e ROW_NUMBER in Oracle

Le funzioni di Oracle Analytic calcolano un valore aggregato in base a un gruppo di righe denominato finestra che determina l'intervallo di righe utilizzato per eseguire i calcoli per la riga corrente. Di seguito sono elencate le funzioni analitiche più utilizzate.
– RANK, DENSE_RANK e ROW_NUMBER
– LAG e LEAD
– FIRST_VALUE e LAST_VALUE

Discuterei delle funzioni di analisi RANK, DENSE_RANK e ROW_NUMBER. Sono di natura abbastanza simile e dobbiamo usarle in base ai requisiti. Spiegherei anche la differenza tra loro

Ecco la sintassi generale

funzione_analitica([ argomenti ]) OVER ([ query_partition_clause ] [ order_by_clause  ])

Funzione ROW_NUMBER in Oracle

RIGA_NUMERO assegna un numero univoco a ciascuna riga della stessa finestra nella sequenza ordinata di righe specificata da order_by_clause.

Per prima cosa creiamo dati di esempio

CREA TABELLA "DEPT"( "DEPTNO" NUMBER(2,0),"DNAME" VARCHAR2(14),"LOC" VARCHAR2(13),VINCOLI "PK_DEPT" CHIAVE PRIMARIA ("DEPTNO"))CREA TABELLA " EMP"( "EMPNO" NUMBER(4,0),"ENAME" VARCHAR2(10),"JOB" VARCHAR2(9),"MGR" NUMBER(4,0),"HIREDATE" DATE,"SAL" NUMBER(7 ,2), NUMERO "COMM"(7,2), NUMERO "DEPTNO"(2,0), CONSTRAINT "PK_EMP" CHIAVE PRIMARIA ("EMPNO"), CONTRAINT "FK_DEPTNO" CHIAVE ESTERA ("DEPTNO") RIFERIMENTI "DEPT " ("DEPTNO") ENABLE);SQL> desc empName Null? Tipo---- ---- -----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? Digitare---- ----- ----DEPTNO NOT NULL NUMBER(2)DNAME VARCHAR2(14)LOC VARCHAR2(13)inserire nei valori DEPT(10, 'CONTABILITÀ', 'NEW YORK');inserire in valori di reparto(20, 'RESEARCH', 'DALLAS');inserire in valori di reparto(30, 'RESEARCH', 'DELHI');inserire valori di reparto(40, 'RESEARCH', 'MUMBAI');commit;inserire in emp values( 7839, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 28573, null, 10 );insert in emp values( 7782, 'Clara ', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 0, null, 10 );insert in emp values( 7934, 'Blake', 'MANAGER', 7839 , to_date('1-5-2007','dd-mm-yyyy'), 0, null, 10 );insert in emp values( 7788, 'Scott', 'ANALYST', 7788, to_date('9-6 -2012','dd-mm-yyyy'), 30000, null, 20 );insert in emp values( 7902, 'Bill', 'ANALYST', 7832, to_date('9-6-2012','dd- mm-aaaa'), 30000, null, 20 );insert in emp values( 7876, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 11000 , null, 20 );insert in emp values( 7369, 'TPM1', 'ANALYST', 7566, to_date('9-6-2017',' gg-mm-aaaa'), 8000, null, 20 );insert in emp values( 7698, 'A1', 'ANALYST', 7788, to_date('9-6-2017','dd-mm-yyyy') , 28500, null, 30 );insert in emp values( 7499, 'A2', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 16000, null, 30 );insert in emp values( 7844, 'A3', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-aaaa'), 15000, null, 30 );insert in emp values( 7654 , 'A4', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );insert in emp values( 7521, 'A5', 'ANALYST ', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );insert in emp values( 7900, 'A6', 'ANALYST', 77698, to_date(' 9-7-2017','gg-mm-aaaa'), 0, null, 30 );commit;
SQL> desc emp Nome Null? Tipo ----------------------------------------- -------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) DATA DI assunzione 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 (partizione per reparto per ordine sal) "numero_riga"fromemp;DEPTNO ENAME SAL numero_riga---------- ---------- ---------- ---------- 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 Dolle selezionate. 

Funzione RANK in Oracle

GRADO è quasi uguale a ROW_NUMBER ma le righe con valori uguali, con nella stessa finestra, per cui è specificata la clausola order by ricevono lo stesso rango ma la riga successiva riceve RANK come da ROW_NUMBER.

SQL> selectdeptno, ename, sal, rank() over (partizione per reparto ordina per 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 file selezionati.

Funzione Dense_rank in Oracle

DENSE_RANK è quasi uguale al RANK, ma non lascia spazio tra le righe se uno o più valori sono uguali. Come nell'esempio seguente, TURNER accanto a WARD nello stesso gruppo riceve DENSE_RANK 3.

SQL> selectdeptno, ename, sal, dense_rank() over (partizione per reparto ordina per 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 file selezionati.

Possiamo anche mettere tutti e tre nella singola query

select deptno, ename, sal, row_number() sopra (partizione per reparto ordine per sal) "row_number", rank() sopra (partizione per reparto ordine per sal) "rank", dense_rank() sopra (partizione per reparto order by sal) "dense_rank" da emp; DEPTNO ENAME SAL numero_riga rango rango_denso---------- ---------- ---------- ---------- ---- ------ ---------- 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 3 file preselezionati 6 6  

Possiamo usare Row_number e la funzione RANK per eliminare le righe duplicate

cancella da t dove rowid IN ( seleziona elimina da (seleziona rowid rid, row_number() su (partizione per nome_colonna ordina per rowid) rn da t) dove rn <> 1);

Queste funzioni sono molto utili per  per le prime N e le ultime N query.

L'SQL di seguito può essere utilizzato per trovare lo stipendio più alto in ogni reparto

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

Spero che ti piaccia la spiegazione su RANK, DENSE_RANK e ROW_NUMBER come le funzioni Oracle Analytic e come possiamo utilizzare nella query per analizzare i dati. Dobbiamo prestare molta attenzione durante l'utilizzo di queste funzioni nelle query, altrimenti il ​​risultato sarebbe diverso.

Articoli correlati

Funzione LEAD in Oracle
Funzioni analitiche in Oracle
Domande su Oracle Interview
Oracle Set Operators
Tutorial Oracle Sql
Documentazione Oracle Dense rank