sql >> Base de Datos >  >> RDS >> Oracle

Funciones RANK, DENSE_RANK y ROW_NUMBER en Oracle

Las funciones de Oracle Analytic calculan un valor agregado basado en un grupo de filas llamado ventana que determina el rango de filas utilizado para realizar los cálculos para la fila actual. Las siguientes son las funciones analíticas más utilizadas.
– RANK, DENSE_RANK y ROW_NUMBER
– LAG y LEAD
– FIRST_VALUE y LAST_VALUE

Hablaría sobre las funciones de análisis RANK, DENSE_RANK y ROW_NUMBER. Son de naturaleza bastante similar y debemos usarlas según el requisito. También explicaría la diferencia entre ellas

Aquí está la sintaxis general

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

Función ROW_NUMBER en Oracle

ROW_NUMBER asigna un número único a cada fila de la misma ventana en la secuencia ordenada de filas especificada por order_by_clause.

Primero creemos datos de muestra

CREATE TABLE "DEPT"( "DEPTNO" NUMBER(2,0),"DNAME" VARCHAR2(14),"LOC" VARCHAR2(13),CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO"))CREATE TABLE " EMP"( "EMPNO" NÚMERO (4,0), "ENAME" VARCHAR2 (10), "JOB" VARCHAR2 (9), "MGR" NÚMERO (4,0), "HIREDATE" FECHA, "SAL" NÚMERO (7 ,2),NÚMERO "COMM"(7,2),NÚMERO "DEPTNO"(2,0),RESTRICCIÓN "PK_EMP" CLAVE PRIMARIA ("EMPNO"),RESTRICCIÓN "FK_DEPTNO" CLAVE EXTERNA ("DEPTNO")REFERENCIAS "DEPT " ("NO DEPT") 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 ¿Nulo? Tipo---- ----- ----DEPTNO NOT NULL NUMBER(2)DNAME VARCHAR2(14)LOC VARCHAR2(13)insertar en DEPT valores(10, 'CONTABILIDAD', 'NUEVA YORK');insertar en valores de departamento (20, 'INVESTIGACIÓN', 'DALLAS'); insertar en valores de departamento (30, 'INVESTIGACIÓN', 'DELHI'); insertar en valores de departamento (40, 'INVESTIGACIÓN', 'MUMBAI'); confirmar; insertar en valores emp ( 7839, 'Clark', 'MANAGER', 7839, to_date('9-6-2008', 'dd-mm-yyyy'), 28573, null, 10 ); insertar en valores emp ( 7782, 'Clara ', 'ADMINISTRADOR', 7839, to_date('9-6-2008','dd-mm-yyyy'), 0, null, 10 );insertar en valores emp ( 7934, 'Blake', 'ADMINISTRADOR', 7839 , to_date('1-5-2007','dd-mm-yyyy'), 0, null, 10 );insertar en valores emp ( 7788, 'Scott', 'ANALYST', 7788, to_date('9-6 -2012','dd-mm-yyyy'), 30000, null, 20 );insertar en valores emp ( 7902, 'Bill', 'ANALYST', 7832, to_date('9-6-2012','dd- mm-aaaa'), 30000, nulo, 20 );insertar en valores emp ( 7876, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 11000 , nulo, 20 ); insertar en valores emp ( 7369, 'TPM1', 'ANALYST', 7566, to_date('9-6-2017',' dd-mm-yyyy'), 8000, null, 20 );insertar en valores emp ( 7698, 'A1', 'ANALYST', 7788, to_date('9-6-2017','dd-mm-yyyy') , 28500, nulo, 30 ); insertar en valores emp ( 7499, 'A2', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 16000, null, 30 );insertar en valores emp ( 7844, 'A3', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 15000, null, 30 );insertar en valores emp ( 7654 , 'A4', 'ANALISTA', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );insertar en valores emp ( 7521, 'A5', 'ANALISTA ', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );insertar en valores emp( 7900, 'A6', 'ANALYST', 77698, to_date(' 9-7-2017','dd-mm-aaaa'), 0, nulo, 30 );commit;
SQL> desc emp Nombre ¿Nulo? Tipo ----------------------------------------- -------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) FECHA DE CONTRATACIÓN NÚMERO DE SAL(7,2) NÚMERO DE COMUNICACIÓN (7,2) NÚMERO DE DEPT (2) SQL> seleccione el número de departamento, el recuento (*) del grupo emp por número de departamento; DEPTNO COUNT(*)---------- ---------- 30 6 20 4 10 3SQL> selectdeptno, ename, sal, row_number() over (partición por deptno order by sal) "row_number"fromemp;DEPTNO ENAME SAL row_number---------- ---------- ---------- ---------- 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 Seleccionadas. 

Función RANGO en Oracle

RANGO es casi lo mismo que ROW_NUMBER pero las filas con valores iguales, en la misma ventana, en las que se especifica la cláusula order by reciben el mismo rango, pero la siguiente fila recibe RANK según ROW_NUMBER.

SQL> selectdeptno, ename, sal, rank() over (partición por 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 filas seleccionadas.

Función Dense_rank en Oracle

RANGO_DENSO es casi igual que el RANGO, pero no deja espacio entre las filas si uno o más valores son iguales. Como en el siguiente ejemplo, TURNER junto a WARD en el mismo grupo recibe DENSE_RANK 3.

SQL> selectdeptno, ename, sal, dense_rank() over (partición por 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 filas seleccionadas.

También podemos poner los tres en la consulta única

select deptno, ename, sal, row_number() over (partición por deptno order by sal) "row_number", rank() over (partición por deptno order by sal) "rank", dense_rank() over (partición por deptno orden por sal) "denso_rango" de emp; DEPTNO ENAME SAL número_fila 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 6 filas seleccionadas 6 

Podemos usar la función Row_number y RANK para eliminar las filas duplicadas

eliminar de t donde id_fila IN (seleccione deshacerse de (seleccione id_fila rid, número_de_fila() sobre (partición por nombre_de_columna ordenado por id_fila) rn de t) donde rn <> 1);

Estas funciones son muy útiles para consultas top-N y bottom-N.

El siguiente SQL se puede usar para encontrar el salario más alto en cada departamento

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

Espero que le guste la explicación sobre RANK, DENSE_RANK y ROW_NUMBER como las funciones de Oracle Analytic y cómo podemos usarlas en la consulta para analizar los datos. Tenemos que tener mucho cuidado al usar estas funciones en las consultas, de lo contrario, el resultado sería diferente.

Artículos relacionados

Función LEAD en Oracle
Funciones analíticas en Oracle
Preguntas de la entrevista de Oracle
Operadores de conjuntos de Oracle
Tutorial de Oracle Sql
Documentación densa de Oracle