Oracle
 sql >> база данни >  >> RDS >> Oracle

Как да използвате аналитични функции в oracle (над разделяне по ключова дума)

Тази публикация е част от урока на Oracle SQL и ние ще обсъждаме аналитичните функции в oracle(Over by partition) с примери, подробно обяснение.

Вече проучихме за Oracle Aggregate функцията като avg, sum, count. Да вземем пример

Първо нека създадем примерни данни

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;

Сега примерът за агрегатните функции ще бъде даден по-долу

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

Тук можем да видим, че намалява броя на редовете във всяка от заявките. Сега идват въпросите какво да правим, ако трябва всички редове да бъдат върнати и с count(*)

За този оракул е предоставил набор от аналитични функции. Така че, за да решим последния проблем, можем да запишем като

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

Тук count(*) over (partition by dept_no) е аналитичната версия на агрегатната функция count. Основната ключова работа, която се различава от агрегатната функция, е над разделяне по

Аналитичните функции изчисляват обобщена стойност въз основа на група редове. Те се различават от агрегатните функции по това, че връщат няколко реда за всяка група. Групата от редове се нарича прозорец и се дефинира от analytic_clause.

Ето общия синтаксис

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

Пример

count(*) over (partition by deptno)

avg(Sal) over (partition by deptno)

Нека разгледаме всяка част

клауза_за_раздел
Той дефинира групата от редове. Може да хареса по-долу

дял по deptno :група от редове от едно и също deptno
или
() :Всички редове

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

[ order_by_clause [ windowing_clause] ]

Тази клауза се използва, когато искате да подредите редовете в дяла. Това е особено полезно, ако искате аналитичната функция да вземе предвид реда на редовете.

Пример ще бъде функция row_number

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

Друг пример би бил

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

клауза_прозорец

Това винаги се използва с клауза за подреждане и дава повече контрол върху набора от редове в групата

С клауза Windowing, За всеки ред се дефинира плъзгащ прозорец от редове. Прозорецът определя обхвата от редове, използвани за извършване на изчисленията за текущия ред. Размерите на прозореца могат да се основават или на физически брой редове, или на логически интервал, като време.

Когато се използва поръчка по клауза и нищо не е дадено за windowing_clause, се приема под стойността по подразбиране на windowing_clause
ДИАПАЗОН МЕЖДУ НЕЗГРАНИЧЕН ПРЕДШЕСТВЕН И ТЕКУЩ РЕД или ДИАПАЗОН НЕОГРАНИЧЕН ПРЕДИШЕН
Това означава „Текущият и предишните редове в текущия дял са редовете, които трябва да се използват при изчислението”

Примерът по-долу ясно показва това. Това е средната стойност в отдела

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

Сега windowing_clause може да се дефинира по няколко начина
Нека първо разберем терминологията

РЕДОВЕ определя прозореца във физически единици (редове).
RANGE определя прозореца като логическо отместване. клаузата за прозорец RANGE може да се използва само с  ORDER BY клаузи, съдържащи колони или изрази с числови или датови типове данни
PRECEDING – получаване на редове преди текущия.
СЛЕД – получаване на редове след текущия.
НЕОГРАНИЧЕН – когато се използва с PRECEDING или FOLLOWING, връща всичко преди или след. ТЕКУЩ РЕД

Така че обикновено се определя като

НЕОГРАНИЧЕНИ РЕДОВЕ ПРЕДИШНИ :Текущите и предишните редове в текущия дял са редовете, които трябва да се използват при изчислението

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

ОБХВАТ НЕОГРАНИЧЕН ПРЕДИШЕН :Текущите и предишните редове в текущия дял са редовете, които трябва да се използват при изчислението. Освен това, тъй като диапазонът е посочен, всичко приема тези стойности, които са равни на текущите редове.

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

Може да не видите разликата между диапазон и редове, тъй като hire_date е различна за всички. Разликата ще стане по-ясна, ако използваме sal като ред по клауза

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;

Можете да намерите разликата на ред 6

RANGE value_expr PRECEDING :Прозорецът започва с реда, чиято стойност ORDER BY е редове с числови изрази, по-малки от или предхождащи текущия ред и завършва с обработването на текущия ред.

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

Тук се вземат всички редове, в които стойността за наемане попада в рамките на 365 дни, предхождащи стойността за наемане на текущия ред

ROWS value_expr ПРЕДИШНО :Прозорецът започва с дадения ред и завършва с текущия ред, който се обработва

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

Тук прозорецът започва от 2 реда, предхождащи текущия ред

ДИАПАЗОН МЕЖДУ ТЕКУЩ РЕД и value_expr СЛЕД :Прозорецът започва с текущия ред и завършва с реда, чиято стойност ORDER BY е редове с числови изрази, по-малки от или следващи

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;

РЕДОВЕ МЕЖДУ ТЕКУЩ РЕД и value_expr СЛЕД :Прозорецът започва с текущия ред и завършва с редовете след текущия

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;

ДИАПАЗОН МЕЖДУ НЕОГРАНИЧЕНО ПРЕДШЕСТВАЩО И НЕОГРАНИЧЕНО СЛЕДВАНЕ

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;

ДИАПАЗОН МЕЖДУ value_expr ПРЕДИШЕН и value_expr СЛЕД

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.

Някои важни бележки
(1) Аналитичните функции са последният набор от операции, извършени в заявка, с изключение на крайната клауза ORDER BY. Всички обединявания и всички клаузи WHERE, GROUP BY и HAVING са завършени преди обработката на аналитичните функции. Следователно аналитичните функции могат да се показват само в списъка за избор или клаузата ORDER BY.
(2)Аналитичните функции обикновено се използват за изчисляване на кумулативни, преместващи, центрирани и отчетни агрегати.

Надявам се да ви хареса това подробно обяснение на аналитичните функции в oracle (над клауза за дял)

Сродни статии
Функция LEAD в Oracle
Функция DENSE в Oracle
Функция Oracle LISTAGG
Агрегиране на данни с помощта на групови функции
https://docs.oracle.com/cd/E11882_01/ server.112/e41084/functions004.htm


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да изпълните .SQL скриптов файл с помощта на c#

  2. GREATEST() Функция в Oracle

  3. извличане на множество колони, група по дата интервалl

  4. Забавност на подзаявката на Oracle

  5. Защо изпълнението на тази заявка с EXECUTE IMMEDIATE води до неуспех?