Oracle Analytic-funktioner beräknar ett aggregerat värde baserat på en grupp rader som kallas fönster som bestämmer radintervallet som används för att utföra beräkningarna för den aktuella raden. Följande är de mest använda analytiska funktionerna.
– RANK, DENSE_RANK och ROW_NUMBER
– LAG och LEAD
– FIRST_VALUE och LAST_VALUE
Jag skulle diskutera analysfunktionerna RANK, DENSE_RANK och ROW_NUMBER. De är ganska lika till sin natur och vi måste använda dem utifrån kravet. Jag skulle också förklara skillnaden mellan dem
Här är den allmänna syntaxen
analytic_function([ arguments ]) OVER ([ query_partition_clause ] [ order_by_clause ])
ROW_NUMBER-funktion i Oracle
ROW_NUMBER tilldelar ett unikt nummer till varje rad i samma fönster i den ordnade sekvensen av rader som anges av order_by_clause.
Låt oss först skapa exempeldata
SKAPA TABELL "DEPT"( "DEPTNO" NUMMER(2,0),"DNAME" VARCHAR2(14),"LOC" VARCHAR2(13),CONSTRAINT "PK_DEPT" PRIMÄRNYCKEL ("DEPTNO"))SKAPA TABELL " EMP"( "EMPNO" NUMMER(4,0),"ENAME" VARCHAR2(10),"JOBB" VARCHAR2(9),"MGR" NUMMER(4,0),"HIREDATE" DATUM,"SAL" NUMMER(7 ,2),"COMM" NUMMER(7,2),"DEPTNO" NUMMER(2,0), CONSTRAINT "PK_EMP" PRIMÄRNYCKEL ("EMPNO"), CONSTRAINT "FK_DEPTNO" UTLÄNDSK NYCKEL ("DEPTNO")REFERENSER "DEPT " ("DEPTNO") ENABLE);SQL> desc empName Null? Typ---- ---- -----EMPNO INTE NULL NUMMER(4)ENAME VARCHAR2(10)JOBB VARCHAR2(9)MGR NUMMER(4)HYREDATUM NUMMER(7,2)KOMMNUMMER(7,2) )DEPTNO NUMMER(2)SQL> desc deptName Null? Skriv---- ----- ----DEPTNO NOT NULL NUMBER(2)DNAME VARCHAR2(14)LOC VARCHAR2(13)infoga i DEPT-värden(10, 'REKVISNING', 'NEW YORK');infoga i dept values(20, 'RESEARCH', 'DALLAS');insert into dept values(30, 'RESEARCH', 'DELHI');insert into dept values(40, 'RESEARCH', 'MUMBAI');commit;insert into emp values( 7839, 'Clark', 'MANAGER', 7839, to_date('9-6-2008','dd-mm-yyyy'), 28573, null, 10 );insert into emp values( 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','dd-mm-åååå'), 30000, null, 20 );insert into emp values( 7902, 'Bill', 'ANALYST', 7832, to_date('9-6-2012','dd- mm-åååå'), 30000, null, 20 );insert into emp values( 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-åååå'), 8000, null, 20 );insert into emp values( 7698, 'A1', 'ANALYST', 7788, to_date('9-6-2017','dd-mm-yyyy') , 28500, null, 30 );insert into emp values( 7499, 'A2', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 16000, null, 30 );insert into emp values( 7844, 'A3', 'ANALYST', 7698, to_date('9-7-2017','dd-mm-yyyy'), 15000, null, 30 );insert into emp values( 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 Name Null? Typ -------------------------------------------------- ---------------------------- EMPNO NOT NULL NUMBER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMBER(4) UTHYRNINGSDATUM SALNUMMER(7,2) KOMM.NUMMER(7,2) DEPTNO NUMMER(2)SQL> välj avdnr ,antal(*) från anställningsgrupp efter avd.nr; DEPTNO COUNT(*)---------- ---------- 30 6 20 4 10 3SQL> selectdeptno, ename, sal, row_number() över (partition efter deptno order by sal) "row_number"fromemp;DEPTNO ENAME SAL rad_nummer--------- ---------- ---------- ---------- 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 BLAK 28500 6 13 ROWS SELECTED.
RANK-funktion i Oracle
RANK är nästan samma som ROW_NUMBER men rader med lika värden, med i samma fönster, där ordning efter sats anges får samma rang men nästa rad får RANK enligt ROW_NUMBER.
SQL> selectdeptno, ename, sal, rank() over (partition efter deptno ordning efter 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 120000IN 230 WARD 12500 230 TURNER 15000 430 ALLEN 16000 530 BLAKE 28500 6 13 rader valda.
Dense_rank-funktion i Oracle
DENSE_RANK är nästan samma som RANK, men det lämnar inget gap mellan raderna om ett eller flera värden är samma. Som i följande exempel får TURNER bredvid WARD i samma grupp DENSE_RANK 3.
SQL> selectdeptno, ename, sal, dense_rank() över (partition efter deptno ordning efter 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 120000IN 230 WARD 12500 230 TURNER 15000 330 ALLEN 16000 430 BLAKE 28500 5 13 rader valda.
Vi kan också lägga in alla tre i den enda frågan
välj deptno, ename, sal, row_number() över (partition efter avd. ordning efter sal) "row_number", rank() över (partition efter avd. ordning efter sal) "rank", dense_rank() över (partition efter deptno ordning efter sal) "dense_rank" från emp; DEPTNO ENAME SAL rad_nummer rank tät_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 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 6 30 4 3 6 30 40 30 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 1 5 1 5>Vi kan använda Row_number och RANK-funktionen för att ta bort de duplicerade raderna
ta bort från t där rowid IN ( välj fri från (välj rowid fri, rad_nummer() över (partitionering efter kolumnnamn ordning efter rowid) rn från t) där rn <> 1);Dessa funktioner är mycket användbara för för top-N och bottom-N-frågor.
Nedanstående SQL kan användas för att hitta högsta lönen i varje avdelning
SQL> välj * (selectdeptno, ename, sal, row_number() över (partition efter deptno ordning efter sal) "row_number"fromemp ) där row_number=1;Hoppas du gillar förklaringar på RANK, DENSE_RANK och ROW_NUMBER som Oracle Analytic-funktioner och hur vi kan användas i frågan för att analysera data. Vi måste vara mycket försiktiga när vi använder dessa funktioner i frågorna, annars skulle resultatet bli annorlunda.
Relaterade artiklar
LEAD-funktion i Oracle
Analytiska funktioner i Oracle
Oracle-intervjufrågor
Oracle Set Operators
Oracle Sql-handledning
Dense rank oracle-dokumentation