sql >> Databasteknik >  >> RDS >> Oracle

Hur man använder analytiska funktioner i oracle (överpartition efter nyckelord)

Det här inlägget är en del av Oracle SQL tutorial och vi skulle diskutera analytiska funktioner i Oracle (Over by partition) med exempel, detaljerad förklaring.

Vi har redan studerat om Oracle Aggregate-funktion som avg ,sum ,count. Låt oss ta ett exempel

Låt oss först skapa exempeldata

CREATE TABLE "DEPT"
( "DEPTNO" NUMBER(2,0),
"DNAME" VARCHAR2(14),
"LOC" VARCHAR2(13),
CONSTRAINT "PK_DEPT" PRIMARY KEY ("DEPTNO")
)

CREATE TABLE "EMP"
( "EMPNO" NUMBER(4,0),
"ENAME" VARCHAR2(10),
"JOB" VARCHAR2(9),
"MGR" NUMBER(4,0),
"HIREDATE" DATE,
"SAL" NUMBER(7,2),
"COMM" NUMBER(7,2),
"DEPTNO" NUMBER(2,0),
CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO"),
CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO")
REFERENCES "DEPT" ("DEPTNO") ENABLE
);

SQL> desc emp
Name Null? Type
---- ---- -----
EMPNO NOT NULL NUMBER(4)
ENAME VARCHAR2(10)
JOB VARCHAR2(9)
MGR NUMBER(4)
HIREDATE DATE
SAL NUMBER(7,2)
COMM NUMBER(7,2)
DEPTNO NUMBER(2)

SQL> desc dept
Name Null? Type
---- ----- ----
DEPTNO NOT NULL NUMBER(2)
DNAME VARCHAR2(14)
LOC VARCHAR2(13)


insert into DEPT values(10, 'ACCOUNTING', 'NEW YORK');
insert into 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, 'Allen', 'MANAGER', 7839, to_date('17-11-1981','dd-mm-yyyy'), 20, null, 10 );
insert into emp values( 7782, 'CLARK', 'MANAGER', 7839, to_date('9-06-1981','dd-mm-yyyy'), 0, null, 10 );
insert into emp values( 7934, 'MILLER', 'MANAGER', 7839, to_date('23-01-1982','dd-mm-yyyy'), 0, null, 10 );
insert into emp values( 7788, 'SMITH', 'ANALYST', 7788, to_date('17-12-1980','dd-mm-yyyy'), 800, null, 20 );
insert into emp values( 7902, 'ADAM, 'ANALYST', 7832, to_date('23-05-1987','dd-mm-yyyy'), 1100, null, 20 );
insert into emp values( 7876, 'FORD', 'ANALYST', 7566, to_date('3-12-1981','dd-mm-yyyy'), 3000, null, 20 );
insert into emp values( 7369, 'SCOTT', 'ANALYST', 7566, to_date('19-04-1987','dd-mm-yyyy'), 3000, null, 20 );
insert into emp values( 7698, 'JAMES', 'ANALYST', 7788, to_date('03-12-1981','dd-mm-yyyy'), 950, null, 30 );
insert into emp values( 7499, 'MARTIN', 'ANALYST', 7698, to_date('28-09-1981','dd-mm-yyyy'), 1250, null, 30 );
insert into emp values( 7844, 'WARD', 'ANALYST', 7698, to_date('22-02-1981','dd-mm-yyyy'), 1250, null, 30 );
insert into emp values( 7654, 'TURNER', 'ANALYST', 7698, to_date('08-09-1981','dd-mm-yyyy'), 1500, null, 30 );
insert into emp values( 7521, 'ALLEN', 'ANALYST', 7698, to_date('20-02-1981','dd-mm-yyyy'), 1600, null, 30 );
insert into emp values( 7900, 'BLAKE', 'ANALYST', 77698, to_date('01-05-1981','dd-mm-yyyy'), 2850, null, 30 );
commit;

Nu kommer exemplet på aggregerade funktioner att ges enligt nedan

select count(*) from EMP;
---------
13

select sum (bytes) from dba_segments where tablespace_name='TOOLS';
-----
100

SQL> select deptno ,count(*) from emp group by deptno;

DEPTNO COUNT(*)
---------- ----------
30              6
20              4
10              3

Här kan vi se att det minskar antalet rader i var och en av frågorna. Nu kommer frågor vad vi ska göra om vi behöver ha alla rader returnerade med count(*) också

För det har oraklet tillhandahållit en uppsättning analytiska funktioner. Så för att lösa det sista problemet kan vi skriva som

select empno ,deptno , count(*) over (partition by deptno) from emp group by deptno;

Här är count(*) over (partition by dept_no) den analytiska versionen av count aggregate-funktionen. Det huvudsakliga nyckelarbetet som skiljer sig genom aggregerad funktion är överpartition med

Analytiska funktioner beräknar ett aggregerat värde baserat på en grupp rader. De skiljer sig från aggregerade funktioner genom att de returnerar flera rader för varje grupp. Gruppen av rader kallas ett fönster och definieras av analytic_clausen.

Här är den allmänna syntaxen

analytic_function([ arguments ]) OVER ([ query_partition_clause ] [ order_by_clause [ windowing_clause ] ])

Exempel

count(*) over (partition by deptno)

avg(Sal) over (partition by deptno)

Låt oss gå igenom varje del

query_partition_clause
Det definierade gruppen av rader. Det kan gilla nedan

partition by deptno :grupp av rader av samma deptno
eller
() :Alla rader

SQL> select empno ,deptno , count(*) over () from emp;

[ order_by_clause [ windowing_clause ] ]

Denna klausul används när du vill sortera raderna i partitionen. Detta är särskilt användbart om du vill att analytisk funktion ska beakta ordningen på raderna.

Exempel är funktionen radnummer

SQL> select
deptno, ename, sal, 
 row_number() over (partition by deptno order by sal) "row_number" from emp;

Ett annat exempel skulle vara

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE) running_sum from emp;

Windowing_clause

Detta används alltid med ordna efter klausul och ger mer kontroll över uppsättningen av rader i gruppen

Med Windowing-satsen, för varje rad, definieras ett glidande fönster med rader. Fönstret bestämmer radintervallet som används för att utföra beräkningarna för den aktuella raden. Fönsterstorlekar kan baseras på antingen ett fysiskt antal rader eller ett logiskt intervall som tid.

När du använder order by-sats och inget anges för windowing_clause, tas under standardvärdet för windowing_clausule
RANGE MELLAN UNBOUNDED PRECEDING OCH CURRENT ROW eller RANGE UNBOUNDED PRECEDING
Det betyder "Den nuvarande och föregående raderna i den aktuella partition är raderna som ska användas i beräkningen”

Exemplet nedan visar tydligt detta. Detta är det löpande genomsnittet på avdelningen

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE) running_sum from emp;

Nu kan windowing_clause definieras på flera sätt
Låt oss först förstå terminologin

RADER anger fönstret i fysiska enheter (rader).
RANGE anger fönstret som en logisk offset. RANGE-fönstersatssatsen kan endast användas med  ORDER BY-satser som innehåller kolumner eller uttryck av numeriska eller datumdatatyper
PRECEDING – få rader före den nuvarande.
FÖLJER – få rader efter den aktuella.
OBEGRÄNSAD – när den används med PRECEDING eller FOLLOWING, återgår den allt före eller efter. AKTUELL RAD

Så det definieras generellt som

RADER OBEGRÄNSAD FÖREGÅENDE :De nuvarande och föregående raderna i den aktuella partitionen är de rader som ska användas i beräkningen

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE ROWS UNBOUNDED PRECEDING) running_sum from emp;

OMRÅDE OBEGRÄNSAT FÖREGÅENDE :De nuvarande och föregående raderna i den aktuella partitionen är de rader som ska användas i beräkningen. Eftersom intervallet är specificerat tar allt de värden som är lika med de aktuella raderna.

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE RANGE UNBOUNDED PRECEDING) running_sum from emp;

Du kanske inte ser skillnaden mellan intervall och rader eftersom hire_date är olika för alla. Skillnaden blir tydligare om vi använder sal som order by-klausul

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by sal RANGE UNBOUNDED PRECEDING) running_sum from emp;
SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by sal ROWS UNBOUNDED PRECEDING) running_sum from emp;

Du hittar skillnaden på rad 6

RANGE value_expr PRECEDING :Fönstret börjar med raden vars ORDER BY-värde är numeriska uttrycksrader mindre än, eller föregår, den aktuella raden och slutar med den aktuella raden som bearbetas.

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE RANGE 365 PRECEDING) running_sum from emp;

Här tar det alla rader där hyresdatumsvärdet faller inom 365 dagar före hyresdatumvärdet för den aktuella raden

ROWS value_expr PRECEDING :Fönstret börjar med den angivna raden och slutar med den aktuella raden som bearbetas

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE ROWS 2 PRECEDING) running_sum from emp;

Här börjar fönstret från 2 rader före den aktuella raden

OMRÅDE MELLAN AKTUELL RAD och FÖLJANDE value_expr :Fönstret börjar med den aktuella raden och slutar med raden vars ORDER BY-värde är numeriska uttrycksrader mindre än eller följande

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE ROWS between current row and 1 FOLLOWING) running_sum from emp;

RADER MELLAN AKTUELL RAD och value_expr FÖLJER :Fönstret börjar med den aktuella raden och slutar med raderna efter den aktuella

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE ROWS between current row and 1 FOLLOWING) running_sum from emp;

OMRÅDE MELLAN OBEGRÄNSAD FÖREGÅENDE och OBEGRÄNSAD FÖLJANDE

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE RANGE BETWEEN UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING
) running_sum from emp;

OMRÅDE MELLAN value_expr PRECEDING och value_expr FOLLOWING

SQL> select deptno, ename,hiredate, sal,sum(sal) over (partition by deptno order by HIREDATE RANGE BETWEEN 365 PRECEDING and 365 FOLLOWING
) running_sum from emp; 2

DEPTNO       ENAME      HIREDATE      SAL      RUNNING_SUM
---------- ---------- --------------- ---------- -----------
10           CLARK       09-JUN-81      0          0
10           ALLEN       17-NOV-81      0          0
10           MILLER      23-JAN-82      0          0
20           SMITH       17-DEC-80      800       3800
20           FORD        03-DEC-81      3000      3800
20           SCOTT       19-APR-87      3000      4100
20           ADAMS       23-MAY-87      1100      4100
30           ALLEN       20-FEB-81      1600      9400
30           WARD        22-FEB-81      1250      9400
30           BLAKE       01-MAY-81      2850      9400
30          TURNER       08-SEP-81      1500      9400
30          MARTIN       28-SEP-81      1250      9400
30          JAMES        03-DEC-81      950       9400

13 rows selected.

Några viktiga anmärkningar
(1)Analytiska funktioner är den sista uppsättningen operationer som utförs i en fråga förutom den sista ORDER BY-satsen. Alla joins och alla WHERE-, GROUP BY- och HAVING-satser är slutförda innan de analytiska funktionerna bearbetas. Därför kan analytiska funktioner endast visas i urvalslistan eller ORDER BY-satsen.
(2)Analytiska funktioner används vanligtvis för att beräkna kumulativa, rörliga, centrerade och rapporterande aggregat.

Jag hoppas att du gillar den här detaljerade förklaringen av analytiska funktioner i oracle (över av partitionsklausul)

Relaterade artiklar
LEAD-funktion i Oracle
DENSE-funktion i Oracle
Oracle LISTAGG-funktion
Aggregera data med hjälp av gruppfunktioner
https://docs.oracle.com/cd/E11882_01/ server.112/e41084/functions004.htm


  1. Använda guiden Offline Reorg

  2. SQLAlchemy, Psychopg2 och Postgresql COPY

  3. Oracle DB citat kolumnnamn

  4. Postgresql-kolumnen hittades inte, men visas i Beskriv