sql >> Databasteknik >  >> RDS >> Oracle

RANK, DENSE_RANK och ROW_NUMBER funktioner i Oracle

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


  1. Garanterar UNION ALL ordningen på resultatuppsättningen

  2. Skillnad mellan flytande och decimal datatyp

  3. Kommandon är osynkroniserade; du kan inte köra det här kommandot nu

  4. Upprätthålla ordning i MySQL IN-frågan