Функциите на Oracle Analytic изчисляват обобщена стойност въз основа на група от редове, наречена прозорец, която определя обхвата от редове, използвани за извършване на изчисленията за текущия ред. Следват най-използваните аналитични функции.
– RANK, DENSE_RANK и ROW_NUMBER
– LAG и LEAD
– FIRST_VALUE и LAST_VALUE
Ще обсъждам функциите за анализ RANK, DENSE_RANK и ROW_NUMBER. Те са доста сходни по естество и трябва да използваме въз основа на изискването. Също така ще обясня разликата между тях
Ето общия синтаксис
analytic_function([ аргументи]) НАД ([ query_partition_clause ] [ order_by_clause ])
Функция ROW_NUMBER в Oracle
ROW_NUMBER присвоява уникален номер на всеки ред от същия прозорец в подредената последователност от редове, определена от order_by_clause.
Нека първо създадем примерни данни
СЪЗДАВАНЕ НА ТАБЛИЦА "DEPT"( "DEPTNO" NUMBER(2,0),"DNAME" VARCHAR2(14),"LOC" VARCHAR2(13),CONSTRAINT "PK_DEPT" ПРАВИЛЕН КЛЮЧ ("DEPTNO"))СЪЗДАВАНЕ НА ТАБЛИЦА " EMP"( "EMPNO" NUMBER(4,0),"ENAME" VARCHAR2(10),"JOB" VARCHAR2(9),"MGR" NUMBER(4,0),"HIREDATE" ДАТА,"SAL" NUMBER(7 ,2),"COMM" NUMBER(7,2),"DEPTNO" NUMBER(2,0),ОГРАНИЧЕНИЕ "PK_EMP" ПЪРВИЧЕН КЛЮЧ ("EMPNO"),ОГРАНИЧЕНИЕ "FK_DEPTNO" ВЪНШЕН КЛЮЧ ("DEPTNO") РЕФЕРЕНЦИИ "DEPT " ("DEPTNO") ENABLE);SQL> desc empName Null? Тип---- ---- -----EMPNO НЕ НУЛЕВ НОМЕР(4)ИМЕ VARCHAR2(10)РАБОТА VARCHAR2(9)MGR НОМЕР(4)НОМЕР НА ДАТИ НА НАЕМАНЕ(7,2)НОМЕР НА COMM(7,2 )DEPTNO NUMBER(2)SQL> desc deptName Null? Тип---- ----- ----DEPTNO NOT NULL NUMBER(2)DNAME VARCHAR2(14)LOC VARCHAR2(13)вмъкнете в DEPT стойности(10, 'ACCOUNTING', 'NEW YORK');вмъкнете в стойности на отдел (20, 'ИЗСЛЕДВАНЕ', 'ДАЛАС');вмъкване в стойности на отдел (30, 'ИЗСЛЕДВАНЕ', 'ДЕЛХИ');вмъкване в стойности на отдел (40, 'ИЗСЛЕДВАНЕ', 'МУМБАЙ');ангажимент;вмъкване в emp стойности( 7839, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 28573, null, 10 );вмъкнете в emp стойности (7782, 'Clara ', 'МЕНИДЖЪР', 7839, to_date('9-6-2008','dd-mm-yyyy'), 0, null, 10 );вмъкнете в emp стойности (7934, 'Blake', 'MANAGER', 7839 , to_date('1-5-2007','dd-mm-yyyy'), 0, null, 10 );вмъкнете в emp стойности (7788, 'Scott', 'ANALYST', 7788, to_date('9-6) -2012','dd-mm-yyyy'), 30000, null, 20 );вмъкнете в emp стойности (7902, 'Bill', 'ANALYST', 7832, to_date('9-6-2012','dd- mm-yyyy'), 30000, null, 20 );вмъкнете в emp стойности (7876, 'TPM', 'ANALYST', 7566, to_date('9-6-2017','dd-mm-yyyy'), 11000 , null, 20 );вмъкнете в emp стойности (7369, 'TPM1', 'ANALYST', 7566, to_date('9-6-2017',' dd-mm-yyyy'), 8000, null, 20 );вмъкнете в emp стойности (7698, 'A1', 'ANALYST', 7788, to_date('9-6-2017','dd-mm-yyyy') , 28500, null, 30 );вмъкнете в emp стойности (7499, 'A2', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 16000, null, 30 );вмъкнете в emp стойности( 7844, 'A3', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 15000, null, 30 );вмъкнете в emp стойности ( 7654 , 'A4', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );вмъкнете в emp стойности (7521, 'A5', 'ANALYST ', 7698, to_date('9-7-2017','dd-mm-yyyy'), 12500, null, 30 );вмъкнете в emp стойности (7900, 'A6', 'ANALYST', 77698, to_date(' 9-7-2017','dd-mm-yyyy'), 0, null, 30 );commit;
SQL> desc emp Име Null? Тип ----------------------------------------- -------- ---------------------------- EMPNO НЕ НУЛЕВ НОМЕР(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER(2)SQL> изберете deptno ,count(*) от emp group by deptno; DEPTNO COUNT(*)---------- ---------- 30 6 20 4 10 3SQL> selectdeptno, ename, sal, row_number() над (разделяне по deptno ред по sal) "номер_ред"отemp;DEPTNO ENAME SAL номер_ред--------- ---------- ---------- ---------- 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 Избрани.
Функция RANK в Oracle
РАНГ е почти същото като ROW_NUMBER, но редовете с равни стойности, в същия прозорец, за който е посочен ред по клауза, получават същия ранг, но следващият ред получава RANK според него ROW_NUMBER.
SQL> selectdeptno, ename, sal, rank() over (разделяне по deptno ред по sal) "RANK"fromemp;DEPTNO ENAME SAL RANK---------- --------- -- ---------- ---------- 10 КЛАРК 0 1 10 МИЛЪР 0 210 Алън 28573 320 СМИТ 8000 120 АДАМС 11000 220 СКОТ 30000 320 ФОРД 30000 330 ДЖЕЙМС 1250 950 230 WARD 12500 230 TURNER 15000 430 ALLEN 16000 530 BLAKE 28500 6 Избрани са 13 реда.
Функция Dense_rank в Oracle
DENSE_RANK е почти същото като RANK, но не оставя празнина между редовете, ако една или повече стойности са еднакви. Както в следващия пример, TURNER до WARD в същата група получава DENSE_RANK 3.
SQL> selectdeptno, ename, sal, dense_rank() over (разделяне по deptno ред по sal) "DENSE_RANK"fromemp;DEPTNO ENAME SAL DENSE_RANK---------- --------- -- ---------- ---------- 10 КЛАРК 0 1 10 МИЛЪР 0 210 Алън 28573 320 СМИТ 8000 120 АДАМС 11000 220 СКОТ 30000 320 ФОРД 30000 330 ДЖЕЙМС 1250 950 230 WARD 12500 230 TURNER 15000 330 ALLEN 16000 430 BLAKE 28500 5 Избрани са 13 реда.
Можем да поставим и трите в единичната заявка
изберете deptno, ename, sal, row_number() над (разделяне по deptno ред по sal) "row_number", rank() над (разделяне по deptno ред по sal) "rank", dense_rank() над (разделяне по deptno поръчка по sal) "dense_rank" от emp; DEPTNO ENAME SAL ред_номер ранг dense_rank---------- ---------- ---------- ---------- ---- ------ ---------- 10 CLARK 0 1 1 1 10 МИЛЪР 0 2 1 1 10 allen 28573 3 3 2 20 SMITH 8000 1 1 1 20 ADAMS 11000 2 2 2 20 SCOTT 3000 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 4 5 5 4 5 5 5 5 5 5 5 5 5 5 1 6 избрани>Можем да използваме функцията Row_number и RANK при изтриване на дублиращи се редове
изтрийте от t, където rowid IN ( изберете rid от (изберете rowid rid, row_number() над (разделяне по име на колона, ред по ред) rn от t) където rn <> 1);Тези функции са много полезни за за заявки отгоре N и отдолу.
SQL по-долу може да се използва за намиране на най-високата заплата във всеки отдел
SQL> изберете * (selectdeptno, ename, sal, row_number() над (разделяне по deptno ред по sal) "row_number"fromemp ), където row_number=1;Надяваме се, че ви харесва обяснението за RANK, DENSE_RANK и ROW_NUMBER като функциите Oracle Analytic и как можем да използваме в заявката за анализ на данните. Трябва да сме много внимателни, докато използваме тези функции в заявките, в противен случай резултатът ще бъде различен.
Сродни статии
LEAD функция в Oracle
Аналитични функции в Oracle
Въпроси за интервю за Oracle
Oracle Set Operators
Урок за Oracle Sql
Документация на Oracle с плътен ранг