Oracle Analytic-funktioner beregner en aggregeret værdi baseret på en gruppe rækker kaldet vindue, som bestemmer rækkevidden af rækker, der bruges til at udføre beregningerne for den aktuelle række. Følgende er de mest brugte analytiske funktioner.
– RANK, DENSE_RANK og ROW_NUMBER
– LAG og LEAD
– FIRST_VALUE og LAST_VALUE
Jeg vil diskutere RANK-, DENSE_RANK- og ROW_NUMBER-analysefunktioner. De ligner hinanden meget, og vi skal bruge dem på grundlag af kravet. Jeg vil også forklare forskellen mellem dem
Her er den generelle syntaks
analytic_function([ arguments ]) OVER ([ query_partition_clause ] [ order_by_clause ])
ROW_NUMBER funktion i Oracle
ROW_NUMBER tildeler et unikt nummer til hver række i samme vindue i den ordnede rækkefølge af rækker, der er angivet af order_by_clause.
Lad os først oprette eksempeldata
OPRET TABEL "DEPT"( "DEPTNO" NUMMER(2,0),"DNAME" VARCHAR2(14),"LOC" VARCHAR2(13),BEGRÆNSNING "PK_DEPT" PRIMÆR NØGLE ("DEPTNO"))OPRET TABEL " EMP"( "EMPNO" NUMMER(4,0),"ENAME" VARCHAR2(10),"JOB" VARCHAR2(9),"MGR" NUMMER(4,0),"UDLEJNING" DATO,"SAL" NUMMER(7 ,2),"KOMM" NUMMER(7,2),"DEPTNO" NUMMER(2,0),BEGRÆNSNING "PK_EMP" PRIMÆR NØGLE ("EMPNO"), CONSTRAINT "FK_DEPTNO" UDENLANDSKE NØGLE ("DEPTNO")REFERENCER "DEPT " ("DEPTNO") ENABLE);SQL> desc empName Null? Type---- ---- -----EMPNO IKKE NULL NUMMER(4)ENAME VARCHAR2(10)JOB VARCHAR2(9)MGR NUMMER(4)UDLEJNING DATO NUMMER(7,2)KOMM NUMMER(7,2) )DEPTNO NUMMER(2)SQL> desc deptName Null? Indtast---- ----- ----DEPTNO NOT NULL NUMMER(2)DNAME VARCHAR2(14)LOC VARCHAR2(13)indsæt i DEPT-værdier(10, 'REGNSKAB', 'NEW YORK');indsæt 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? Skriv -------------------------------------------------- ---------------------------- EMPNO IKKE NULL NUMMER(4) ENAME VARCHAR2(10) JOB VARCHAR2(9) MGR NUMMER(4) UDLEJSDATO SALGNUMMER(7,2) KOMM.NUMMER(7,2) DEPTNO NUMMER(2)SQL> vælg deptno ,count(*) fra emp group by deptno; DEPTNO COUNT(*)---------- ---------- 30 6 20 4 10 3SQL> selectdeptno, ename, sal, row_number() over (partition efter deptno rækkefølge efter sal) "row_number"fromemp;DEPTNO ENAME SAL række_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 BLAKE 28500 6 13 ROWS VÆLGT.
RANK-funktion i Oracle
RANK er næsten den samme som ROW_NUMBER, men rækker med lige værdier, med i samme vindue, hvor der er angivet rækkefølge efter klausul, modtager samme rang, men næste række modtager RANK i henhold til ROW_NUMBER.
SQL> selectdeptno, ename, sal, rank() over (partition efter deptno rækkefølge 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 rækker valgt.
Dense_rank-funktion i Oracle
DENSE_RANK er næsten den samme som RANK, men den efterlader ikke mellemrum mellem rækkerne, hvis en eller flere værdier er ens. Som i følgende eksempel modtager TURNER ved siden af WARD i samme gruppe DENSE_RANK 3.
SQL> selectdeptno, ename, sal, dense_rank() over (partition efter deptno rækkefølge 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 rækker valgt.
Vi kan også sætte alle tre i den enkelte forespørgsel
vælg deptno, ename, sal, row_number() over (partition efter deptno rækkefølge efter sal) "row_number", rank() over (partition efter deptno rækkefølge efter sal) "rank", dense_rank() over (partition efter deptno rækkefølge efter sal) "dense_rank" fra emp; DEPTNO ENAME SAL row_number rank dense_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 50 ALLEN 60 5 5 6 5 5 0 5 5 6 5 6 5 6 5 6 0 3 0 5 0 5 6 5 valgt.>Vi kan bruge Row_number og RANK-funktionen til at slette de duplikerende rækker
slet fra t hvor rowid IN (vælg fri fra (vælg rowid fri, rækkenummer() over (partition efter kolonnenavn rækkefølge efter rowid) rn fra t) hvor rn <> 1);Disse funktioner er meget nyttige til for top-N og bottom-N-forespørgsler.
Nedenstående SQL kan bruges til at finde toplønnen i hver afdeling
SQL> vælg * (selectdeptno, ename, sal, row_number() over (partition efter deptno rækkefølge efter sal) "row_number"fromemp ) hvor row_number=1;Håber du kan lide forklaring på RANK, DENSE_RANK og ROW_NUMBER som Oracle Analytic-funktioner og hvordan vi kan bruges i forespørgslen til at analysere dataene. Vi skal være meget forsigtige, når vi bruger disse funktioner i forespørgslerne, ellers ville resultatet blive anderledes.
Relaterede artikler
LEAD-funktion i Oracle
Analytiske funktioner i Oracle
Oracle-interviewspørgsmål
Oracle Set Operators
Oracle Sql-vejledning
Oracle-dokumentation med tæt rangering