Funkce Oracle Analytic počítají agregovanou hodnotu na základě skupiny řádků nazývaných okno, které určuje rozsah řádků použitých k provedení výpočtů pro aktuální řádek. Následují nejpoužívanější analytické funkce.
– RANK, DENSE_RANK a ROW_NUMBER
– LAG a LEAD
– FIRST_VALUE a LAST_VALUE
Diskutoval bych o analytických funkcích RANK, DENSE_RANK a ROW_NUMBER. Jsou svou povahou dost podobné a musíme je používat na základě požadavku. Také bych vysvětlil rozdíl mezi nimi
Zde je obecná syntaxe
analytická_funkce([ argumenty ]) OVER ([ klauzule_oddílu dotazu ] [ klauzule podle objednávky ])
Funkce ROW_NUMBER v Oracle
ROW_NUMBER přiřadí jedinečné číslo každému řádku stejného okna v uspořádané posloupnosti řádků specifikované v order_by_clause.
Nejprve vytvořte ukázková data
VYTVOŘIT TABULKU "ODDĚLENÍ"( "DEPTNO" ČÍSLO(2,0),"DNAME" VARCHAR2(14),,"LOC" VARCHAR2(13),OMEZENÍ "PK_DEPT" PRIMÁRNÍ KLÍČ ("DEPTNO"))VYTVOŘIT TABULKU " EMP"( "EMPNO" ČÍSLO(4,0);ENAME" VARCHAR2(10),"PRÁCE" VARCHAR2(9),"MGR" ČÍSLO(4,0),"DATUM NÁBORU"DATUM "SAL" ČÍSLO(7 ,2),"COMM" NUMBER(7,2),,"DEPTNO" NUMBER(2,0),OMEZENÍ "PK_EMP" PRIMÁRNÍ KLÍČ ("EMPNO"),OMEZENÍ "FK_DEPTNO" CIZÍ KLÍČ ("DEPTNO")REFERENCE "ODD. " ("DEPTNO") ENABLE);SQL> desc empName Null? Typ---- ---- -----EMPNO NENÍ NULL ČÍSLO(4)JMÉNO VARCHAR2(10)PRÁCE VARCHAR2(9)ČÍSLO MGR(4)ČÍSLO DATUM NÁBORU(7,2)ČÍSLO KOMU (7,2) )DEPTNO NUMBER(2)SQL> desc deptName Null? Typ---- ----- ----DEPTNO NOT NULL NUMBER(2)DNAME VARCHAR2(14)LOC VARCHAR2(13)vložit do DEPT values(10, 'ÚČETNICTVÍ', 'NEW YORK');vložit do dept values(20, 'RESEARCH', 'DALLAS');insert into dept values(30, 'RESEARCH', 'DELHI');insert into dept values(40, 'RESEARCH', 'MUMBAI');commit;insert into hodnoty emp( 7839, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 28573, null, 10); vložit do hodnot emp ( 7782, 'Clara ', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 0, null, 10); vložit do hodnot emp ( 7934, 'Blake', 'MANAGER', 7839 , to_date('1-5-2007','dd-mm-yyyy'), 0, null, 10 );vložit do hodnot emp( 7788, 'Scott', 'ANALYST', 7788, to_date('9-6 -2012','dd-mm-yyyy'), 30 000, null, 20); vložit do hodnot emp ( 7902, 'Bill', 'ANALYST', 7832, to_date('9-6-2012','dd- mm-yyyy'), 30000, null, 20); vložit do hodnot emp ( 7876, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 11000 , null, 20 );insert into emp values( 7369, 'TPM1', 'ANALYST', 7566, to_date('9-6-2017',' dd-mm-yyyy'), 8000, null, 20 );vložit do hodnot emp ( 7698, 'A1', 'ANALYST', 7788, to_date('9-6-2017','dd-mm-yyyy') , 28500, null, 30 );vložit do hodnot emp ( 7499, 'A2', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 16000, null, 30 );vložit do hodnot emp( 7844, 'A3', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-rrrr'), 15000, null, 30 );vložit do hodnot emp( 7654 , 'A4', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );vložit do hodnot emp ( 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 Název Null? Typ ----------------------------------------- --------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) DATUM NÁBORU ČÍSLO PRODEJ (7,2) ČÍSLO KOMU (7,2) ČÍSLO DEPTNO(2)SQL> vybrat deptno ,count(*) z emp group by deptno; DEPTNO COUNT(*)---------- ---------- 30 6 20 4 10 3SQL> selectdeptno, ename, sal, row_number() over (partition by 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 TOUNDER 15000 430 Allen 16000 530 Blake Blake 28500 6 13 ROWS.Funkce RANK v Oracle
HODNOCENÍ je téměř stejný jako ROW_NUMBER, ale řádky se stejnými hodnotami ve stejném okně, pro které je zadáno pořadí podle klauzule, obdrží stejnou hodnost, ale další řádek obdrží RANK jako 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 JAMES 130500 320 JAMES 33050 3050 230 WARD 12500 230 TURNER 15000 430 ALLEN 16000 530 BLAKE 28500 6 13 vybraných řádků.Funkce Dense_rank v Oracle
DENSE_RANK je téměř stejná jako RANK, ale nezanechává mezeru mezi řádky, pokud je jedna nebo více hodnot stejných. Stejně jako v následujícím příkladu TURNER vedle WARD ve stejné skupině obdrží DENSE_RANK 3.
SQL> selectdeptno, ename, sal, dense_rank() over (rozdělení podle deptno pořadí podle 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 JAMES 130500 320 JAMES 33050 3050 230 WARD 12500 230 TURNER 15000 330 ALLEN 16000 430 BLAKE 28500 5 13 vybraných řádků.Můžeme vložit všechny tři do jediného dotazu také
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 pořadí podle sal) "dense_rank" z emp; DEPTNO ENAME SAL číslo_řádku pořadí hustá_hodnost---------- ---------- ---------- --------- ---- ------ ---------- 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 2 3320 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 LA 3 2 30 LA 3000 3000 KE 2 TURNER 3 05 06 065 0,06 5 vybraných>Při mazání duplikujících se řádků můžeme použít Row_number a RANK funkce
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);Tyto funkce jsou velmi užitečné pro pro top-N a bottom-N dotazy.
Níže uvedený SQL lze použít k nalezení nejvyšší mzdy v každém oddělení
SQL> select * (selectdeptno, ename, sal, row_number() over (partition by deptno order by sal) "row_number"fromemp ) where row_number=1;Doufám, že se vám líbí vysvětlení o RANK, DENSE_RANK a ROW_NUMBER, jako jsou funkce Oracle Analytic a jak můžeme v dotazu analyzovat data. Při používání těchto funkcí v dotazech musíme být velmi opatrní, jinak by byl výsledek jiný.
Související články
Funkce LEAD v Oracle
Analytické funkce v oracle
Otázky k rozhovoru s Oracle
Oracle Set Operators
Výukový program Oracle Sql
Hustá dokumentace oracle