sql >> Database teknologi >  >> RDS >> Oracle

Sådan bruger du analytiske funktioner i Oracle (Overpartition efter søgeord)

Dette indlæg er en del af Oracle SQL tutorial, og vi vil diskutere analytiske funktioner i Oracle (Over af partition) med eksempler, detaljeret forklaring.

Vi har allerede studeret om Oracle Aggregate-funktion som avg, sum, count. Lad os tage et eksempel

Lad os først oprette prøvedataene

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 vil eksemplet på aggregerede funktioner blive givet som nedenfor

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

Her kan vi se, at det reducerer antallet af rækker i hver af forespørgslerne. Nu kommer spørgsmålene, hvad vi skal gøre, hvis vi også skal have alle rækkerne returneret med count(*)

For det orakel har leveret et sæt analytiske funktioner. Så for at løse det sidste problem kan vi skrive som

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

Her er count(*) over (partition af dept_no) den analytiske version af count aggregate-funktionen. Hovednøglearbejdet, som er forskelligt efter aggregeret funktion, er over partition af

Analytiske funktioner beregner en aggregeret værdi baseret på en gruppe rækker. De adskiller sig fra aggregerede funktioner ved, at de returnerer flere rækker for hver gruppe. Gruppen af ​​rækker kaldes et vindue og er defineret af analytic_clause.

Her er den generelle syntaks

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

Eksempel

count(*) over (partition by deptno)

avg(Sal) over (partition by deptno)

Lad os gennemgå hver del

query_partition_clause
Det definerede gruppen af ​​rækker. Det kan lide nedenfor

partition efter deptno :gruppe af rækker af samme deptno
eller
() :Alle rækker

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

[ rækkefølge_efter_klausul [ vinduesklausul ] ]

Denne klausul bruges, når du vil bestille rækkerne i partitionen. Dette er især nyttigt, hvis du vil have analytisk funktion til at overveje rækkefølgen af ​​rækkerne.

Eksempel vil være rækkenummer-funktionen

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

Et andet eksempel ville være

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

Windowing_clause

Dette bruges altid med orden efter klausul og giver mere kontrol over rækkerne i gruppen

Med Windowing-klausul er der defineret et glidende vindue af rækker for hver række. Vinduet bestemmer rækkevidden af ​​rækker, der bruges til at udføre beregningerne for den aktuelle række. Vinduesstørrelser kan være baseret på enten et fysisk antal rækker eller et logisk interval såsom tid.

Når du bruger orden efter klausul, og der ikke er angivet noget for windowing_clause, tages under standardværdien af ​​windowing_clausule
RANGE MELLEM UNBOUNDED PRECEDING OG CURRENT ROW eller RANGE UNBOUNDED PRECEDING
Det betyder "Den aktuelle og forrige række i den aktuelle partition er de rækker, der skal bruges i beregningen"

Eksemplet nedenfor viser dette tydeligt. Dette er det løbende gennemsnit i afdelingen

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

Nu kan windowing_clause defineres på flere måder
Lad os først forstå terminologien

RÆKKER angiver vinduet i fysiske enheder (rækker).
RANGE angiver vinduet som en logisk offset. RANGE-vinduessætningen kan kun bruges med  ORDER BY-sætninger, der indeholder kolonner eller udtryk af numeriske eller datodatatyper
PRECEDING – få rækker før den nuværende.
FØLGER – få rækker efter den nuværende.
UNGRENSEDE – når den bruges med PRECEDING eller FOLLOWING, vender den tilbage før eller efter. NUVÆRENDE RÆKKE

Så det er generelt defineret som

RÆKKER UBEGRÆNSET FOREGÅENDE :Den nuværende og forrige række i den aktuelle partition er de rækker, der skal bruges i beregningen

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

OMRÅDE UBEGRÆNSET FOREGÅENDE :Den nuværende og forrige række i den aktuelle partition er de rækker, der skal bruges i beregningen. Da området er angivet, tager det alle de værdier, der er lig med de aktuelle rækker.

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

Du kan muligvis ikke se forskellen mellem interval og rækker, da leje_dato er forskellig for alle. Forskellen bliver mere tydelig, hvis vi bruger sal som orden efter 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 kan finde forskellen på linje 6

RANGE value_expr PRECEDING :Vinduet begynder med rækken, hvis ORDER BY-værdi er numeriske udtryksrækker mindre end eller foran den aktuelle række og slutter med den aktuelle række, der behandles.

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

Her tager det alle de rækker, hvor lejedatoværdien falder inden for 365 dage før lejedatoværdien for den aktuelle række

ROWS value_expr PRECEDING :Vinduet begynder med den angivne række og slutter med den aktuelle række, der behandles

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

Her starter vinduet fra 2 rækker forud for den aktuelle række

OMRÅDE MELLEM AKTUEL RÆKKE og værdi_udt. FØLGENDE :Vinduet begynder med den aktuelle række og slutter med den række, hvis ORDER BY-værdi er numeriske udtryksrækker mindre end eller følgende

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;

RÆKKER MELLEM AKTUELLE RÆKKE og værdi_udt. FØLGENDE :Vinduet begynder med den aktuelle række og slutter med rækkerne efter den aktuelle

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 MELLEM UBEGRÆNSET FOREGÅENDE og UBEGRÆNSET FØLGENDE

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;

RANGE MELLEM value_expr PRECEDING og 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.

Nogle vigtige bemærkninger
(1)Analytiske funktioner er det sidste sæt af operationer, der udføres i en forespørgsel, bortset fra den sidste ORDER BY-klausul. Alle joins og alle WHERE-, GROUP BY- og HAVING-sætninger er afsluttet, før de analytiske funktioner behandles. Derfor kan analytiske funktioner kun vises i den valgte liste eller ORDER BY-klausulen.
(2)Analytiske funktioner bruges almindeligvis til at beregne kumulative, flyttende, centrerede og rapporterende aggregater.

Jeg håber, du kan lide denne detaljerede forklaring af analytiske funktioner i oracle (over af partitionsklausul)

Relaterede artikler
LEAD-funktion i Oracle
DENSE-funktion i Oracle
Oracle LISTAGG-funktion
Aggregering af data ved hjælp af gruppefunktioner
https://docs.oracle.com/cd/E11882_01/ server.112/e41084/functions004.htm


  1. Hent sidst kendte værdi for hver kolonne i en række

  2. Oracle .Net ManagedDataAccess Fejl:Kunne ikke indlæse typen 'OracleInternal.Common.ConfigBaseClass' fra assembly

  3. Flere måder at indsætte opdelte afgrænsede strenge i en kolonne

  4. Oracle SQL PIVOT-tabel