sql >> Database >  >> RDS >> Oracle

Analytische functies gebruiken in Oracle (Over partitie op trefwoord)

Dit bericht maakt deel uit van de Oracle SQL-zelfstudie en we zouden analytische functies in Oracle (Over per partitie) bespreken met voorbeelden, gedetailleerde uitleg.

We hebben al gestudeerd over Oracle Aggregate-functies zoals avg,sum,count. Laten we een voorbeeld nemen

Laten we eerst de voorbeeldgegevens maken

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 wordt het voorbeeld van geaggregeerde functies gegeven zoals hieronder

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

Hier kunnen we zien dat het het aantal rijen in elk van de query's vermindert. Nu komen er vragen wat we moeten doen als we alle rijen moeten teruggeven met count(*) ook

Want dat orakel heeft een reeks analytische functies verschaft. Dus om het laatste probleem op te lossen, kunnen we schrijven als

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

Hier is count(*) over (partition by dept_no) de analytische versie van de count-aggregatiefunctie. Het belangrijkste sleutelwerk dat per aggregatiefunctie verschilt, is over partitie door

Analytische functies berekenen een totale waarde op basis van een groep rijen. Ze verschillen van geaggregeerde functies doordat ze meerdere rijen voor elke groep retourneren. De groep rijen wordt een venster genoemd en wordt gedefinieerd door de analytic_clause.

Hier is de algemene syntaxis

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

Voorbeeld

count(*) over (partition by deptno)

avg(Sal) over (partition by deptno)

Laten we elk onderdeel doornemen

query_partition_clause
Het definieerde de groep rijen. Het kan zoals hieronder

partitie door deptno :groep rijen van dezelfde deptno
of
() :Alle rijen

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

[ order_by_clause [ windowing_clause ] ]

Deze clausule wordt gebruikt wanneer u de rijen in de partitie wilt ordenen. Dit is vooral handig als u wilt dat de analytische functie rekening houdt met de volgorde van de rijen.

Voorbeeld is de functie row_number

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

Een ander voorbeeld zou zijn

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

Windowing_clause

Dit wordt altijd gebruikt met volgorde per clausule en geeft meer controle over de reeks rijen in de groep

Met Windowing-clausule wordt voor elke rij een glijdend venster met rijen gedefinieerd. Het venster bepaalt het rijbereik dat wordt gebruikt om de berekeningen voor de huidige rij uit te voeren. Venstergroottes kunnen gebaseerd zijn op een fysiek aantal rijen of op een logisch interval zoals tijd.

Bij gebruik van de volgorde per clausule en er wordt niets gegeven voor windowing_clause, wordt onder de standaardwaarde van de windowing_clause genomen
BEREIK TUSSEN UNBOUNDED VOORAFGAANDE EN HUIDIGE RIJ of RANGE UNBOUNDED PRECEDING
Het betekent "De huidige en vorige rijen in de huidige partitie zijn de rijen die in de berekening moeten worden gebruikt”

Onderstaand voorbeeld geeft dit duidelijk weer. Dit is het lopende gemiddelde op de afdeling

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

Nu kan windowing_clause op een aantal manieren worden gedefinieerd
Laten we eerst de terminologie begrijpen

RIJEN specificeert het venster in fysieke eenheden (rijen).
RANGE specificeert het venster als een logische offset. de vensterclausule RANGE kan alleen worden gebruikt met ORDER BY-clausules die kolommen of uitdrukkingen van numerieke of datumgegevenstypen bevatten
VOORGAANDE – krijg rijen voor de huidige.
VOLGENDE – krijg rijen na de huidige.
UNBOUNDED – wanneer gebruikt met PRECEDING of FOLLOWING, keert het allemaal terug voor of na. HUIDIGE RIJ

Dus het wordt over het algemeen gedefinieerd als

RIJEN ONGEBONDEN VOORAFGAANDE :De huidige en vorige rijen in de huidige partitie zijn de rijen die moeten worden gebruikt in de berekening

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

BEREIK ONGEBONDEN VOORAFGAANDE :De huidige en vorige rijen in de huidige partitie zijn de rijen die in de berekening moeten worden gebruikt. Omdat het bereik is opgegeven, worden alle waarden gebruikt die gelijk zijn aan de huidige rijen.

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

Het is mogelijk dat u het verschil tussen het bereik en de rijen niet ziet, aangezien de huurdatum voor iedereen anders is. Het verschil wordt duidelijker als we sal gebruiken als volgorde per clausule

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;

Je kunt het verschil vinden op regel 6

BEREIK value_expr VOORAFGAAND aan :Het venster begint met de rij waarvan de ORDER BY-waarde een numerieke uitdrukkingsrij is die kleiner is dan of voorafgaat aan de huidige rij en eindigt met de huidige rij die wordt verwerkt.

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

Hier zijn alle rijen nodig waar de huurwaarde valt binnen 365 dagen voorafgaand aan de huurprijs van de huidige rij

ROWS value_expr PRECEDING :Het venster begint met de gegeven rij en eindigt met de huidige rij die wordt verwerkt

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

Hier begint het venster vanaf 2 rijen voorafgaand aan de huidige rij

BEREIK TUSSEN HUIDIGE RIJ en value_expr VOLGENDE :Het venster begint met de huidige rij en eindigt met de rij waarvan de ORDER BY-waarde een numerieke uitdrukkingsrij is die kleiner is dan of volgt

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;

RIJEN TUSSEN DE HUIDIGE RIJ en value_expr VOLGENDE :Het venster begint met de huidige rij en eindigt met de rijen na de huidige

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;

BEREIK TUSSEN ONGEBONDEN VOORAFGAANDE en ONGEBONDEN VOLGENDE

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;

BEREIK TUSSEN value_expr PRECEDING en value_expr VOLGENDE

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.

Enkele belangrijke opmerkingen
(1)Analytische functies zijn de laatste reeks bewerkingen die in een query worden uitgevoerd, behalve de laatste ORDER BY-clausule. Alle joins en alle WHERE-, GROUP BY- en HAVING-clausules zijn voltooid voordat de analytische functies worden verwerkt. Daarom kunnen analytische functies alleen voorkomen in de select list of ORDER BY-clausule.
(2)Analytische functies worden vaak gebruikt om cumulatieve, bewegende, gecentreerde en rapportage-aggregaten te berekenen.

Ik hoop dat je deze gedetailleerde uitleg van analytische functies in orakel leuk vindt (over by Partition Clause)

Gerelateerde artikelen
LEAD-functie in Oracle
DENSE-functie in Oracle
Oracle LISTAGG-functie
Aggregatiegegevens met groepsfuncties
https://docs.oracle.com/cd/E11882_01/ server.112/e41084/functions004.htm


  1. SQL Server-lus - hoe loop ik door een set records?

  2. SQL Server (localdb)\v11.0 uitgelegd

  3. datetime naar totalminute in sql

  4. Rijwaarden samenvoegen T-SQL