Probably the easiest way to understand analytic functions is to start
 by looking at aggregate functions. An aggregate function, as the name 
suggests, aggregates data from several rows into a single result row. 
For example, we might use the 
SELECT deptno, AVG(sal) FROM emp
GROUP BY deptno
ORDER BY deptno;
DEPTNO AVG(SAL)
---------- ----------
10 2916.66667
20 2175 30
1566.66667
SQL>
Analytic functions also operate on subsets of rows, similar to aggregate functions in
analytic_function([ arguments ]) OVER (analytic_clause) The
[ query_partition_clause ] [ order_by_clause [ windowing_clause ] ] The sub-elements of the
BREAK ON deptno SKIP 1 DUPLICATES SELECT empno, deptno, sal, AVG(sal) OVER (PARTITION BY deptno) AS avg_dept_sal FROM emp; EMPNO DEPTNO SAL AVG_DEPT_SAL ---------- ---------- ---------- ------------ 7782 10 2450 2916.66667 7839 10 5000 2916.66667 7934 10 1300 2916.66667 7566 20 2975 2175 7902 20 3000 2175 7876 20 1100 2175 7369 20 800 2175 7788 20 3000 2175 7521 30 1250 1566.66667 7844 30 1500 1566.66667 7499 30 1600 1566.66667 7900 30 950 1566.66667 7698 30 2850 1566.66667 7654 30 1250 1566.66667 SQL>
BREAK ON deptno SKIP 1 DUPLICATES SELECT empno, deptno, sal, FIRST_VALUE(sal IGNORE NULLS) OVER (PARTITION BY deptno) AS first_sal_in_dept FROM emp; EMPNO DEPTNO SAL FIRST_SAL_IN_DEPT ---------- ---------- ---------- ----------------- 7782 10 2450 2450 7839 10 5000 2450 7934 10 1300 2450 7566 20 2975 2975 7902 20 3000 2975 7876 20 1100 2975 7369 20 800 2975 7788 20 3000 2975 7521 30 1250 1250 7844 30 1500 1250 7499 30 1600 1250 7900 30 950 1250 7698 30 2850 1250 7654 30 1250 1250 SQL> Now compare the values of the
SELECT empno, deptno, sal, FIRST_VALUE(sal IGNORE NULLS) OVER (PARTITION BY deptno ORDER BY sal ASC NULLS LAST) AS first_val_in_dept FROM emp; EMPNO DEPTNO SAL FIRST_VAL_IN_DEPT ---------- ---------- ---------- ----------------- 7934 10 1300 1300 7782 10 2450 1300 7839 10 5000 1300 7369 20 800 800 7876 20 1100 800 7566 20 2975 800 7788 20 3000 800 7902 20 3000 800 7900 30 950 950 7654 30 1250 950 7521 30 1250 950 7844 30 1500 950 7499 30 1600 950 7698 30 2850 950 SQL> In this case the "
It is important to understand how the
AVG aggregate function to give us an average of all the employee salaries in the EMP table.SELECT AVG(sal) FROM emp; AVG(SAL) ---------- 2073.21429 SQL>
The
GROUP BY clause allows us to apply aggregate 
functions to subsets of rows. For example, we might want to display the 
average salary for each department.SELECT deptno, AVG(sal) FROM emp
GROUP BY deptno
ORDER BY deptno;
DEPTNO AVG(SAL)
---------- ----------
10 2916.66667
20 2175 30
1566.66667
SQL>
In both cases, the aggregate function reduces the number of rows returned by the query.
Analytic functions also operate on subsets of rows, similar to aggregate functions in
GROUP BY
 queries, but they do not reduce the number of rows returned by the 
query. For example, the following query reports the salary for each 
employee, along with the average salary of the employees within the 
department.SET PAGESIZE 50
BREAK ON deptno SKIP 1 DUPLICATES
SELECT empno, deptno, sal,
       AVG(sal) OVER (PARTITION BY deptno) AS avg_dept_sal
FROM   emp;
     EMPNO     DEPTNO        SAL AVG_DEPT_SAL
---------- ---------- ---------- ------------
      7782         10       2450   2916.66667
      7839         10       5000   2916.66667
      7934         10       1300   2916.66667
      7566         20       2975         2175
      7902         20       3000         2175
      7876         20       1100         2175
      7369         20        800         2175
      7788         20       3000         2175
      7521         30       1250   1566.66667
      7844         30       1500   1566.66667
      7499         30       1600   1566.66667
      7900         30        950   1566.66667
      7698         30       2850   1566.66667
      7654         30       1250   1566.66667
14 rows selected.
SQL>
This timeAVGis an analytic function, operating on the group of rows defined by the contents of theOVERclause. This group of rows is known as a window, which is why analytic functions are sometimes referred to as window[ing] functions. Notice how theAVGfunction is still reporting the departmental average, like it did in theGROUP BYquery, but the result is present in each row, rather than reducing the total number of rows returned. This is because analytic functions are performed on a result set after all join,WHERE,GROUP BYandHAVINGclauses are complete, but before the finalORDER BYoperation is performed.
Analytic Function Syntax
There are some variations in the syntax of the individual analytic functions, but the basic syntax for an analytic function is as follows.analytic_function([ arguments ]) OVER (analytic_clause) The
analytic_clause breaks down into the following optional elements.[ query_partition_clause ] [ order_by_clause [ windowing_clause ] ] The sub-elements of the
analytic_clause each have their own syntax diagrams, shown here. Rather than repeat the syntax diagrams, the following sections describe what each section of the analytic_clause is used for.query_partition_clause
Thequery_partition_clause divides the result set into 
partitions, or groups, of data. The operation of the analytic function 
is restricted to the boundary imposed by these partitions, similar to 
the way a GROUP BY clause affects the action of an aggregate function. If the query_partition_clause is omitted, the whole result set is treated as a single partition. The following query uses an empty OVER clause, so the average presented is based on all the rows of the result set.CLEAR BREAKS
SELECT empno, deptno, sal,
       AVG(sal) OVER () AS avg_sal
FROM   emp;
     EMPNO     DEPTNO        SAL    AVG_SAL
---------- ---------- ---------- ----------
      7369         20        800 2073.21429
      7499         30       1600 2073.21429
      7521         30       1250 2073.21429
      7566         20       2975 2073.21429
      7654         30       1250 2073.21429
      7698         30       2850 2073.21429
      7782         10       2450 2073.21429
      7788         20       3000 2073.21429
      7839         10       5000 2073.21429
      7844         30       1500 2073.21429
      7876         20       1100 2073.21429
      7900         30        950 2073.21429
      7902         20       3000 2073.21429
      7934         10       1300 2073.21429
SQL>
---If we change the
OVER clause to include a query_partition_clause based on the department, the averages presented are specifically for the department the employee belongs too.BREAK ON deptno SKIP 1 DUPLICATES SELECT empno, deptno, sal, AVG(sal) OVER (PARTITION BY deptno) AS avg_dept_sal FROM emp; EMPNO DEPTNO SAL AVG_DEPT_SAL ---------- ---------- ---------- ------------ 7782 10 2450 2916.66667 7839 10 5000 2916.66667 7934 10 1300 2916.66667 7566 20 2975 2175 7902 20 3000 2175 7876 20 1100 2175 7369 20 800 2175 7788 20 3000 2175 7521 30 1250 1566.66667 7844 30 1500 1566.66667 7499 30 1600 1566.66667 7900 30 950 1566.66667 7698 30 2850 1566.66667 7654 30 1250 1566.66667 SQL>
order_by_clause
Theorder_by_clause is used to order rows, or siblings, 
within a partition. So if an analytic function is sensitive to the order
 of the siblings in a partition you should include an order_by_clause. The following query uses the FIRST_VALUE
 function to return the first salary reported in each department. Notice
 we have partitioned the result set by the department, but there is no order_by_clause.BREAK ON deptno SKIP 1 DUPLICATES SELECT empno, deptno, sal, FIRST_VALUE(sal IGNORE NULLS) OVER (PARTITION BY deptno) AS first_sal_in_dept FROM emp; EMPNO DEPTNO SAL FIRST_SAL_IN_DEPT ---------- ---------- ---------- ----------------- 7782 10 2450 2450 7839 10 5000 2450 7934 10 1300 2450 7566 20 2975 2975 7902 20 3000 2975 7876 20 1100 2975 7369 20 800 2975 7788 20 3000 2975 7521 30 1250 1250 7844 30 1500 1250 7499 30 1600 1250 7900 30 950 1250 7698 30 2850 1250 7654 30 1250 1250 SQL> Now compare the values of the
FIRST_SAL_IN_DEPT column when we include an order_by_clause to order the siblings by ascending salary.SELECT empno, deptno, sal, FIRST_VALUE(sal IGNORE NULLS) OVER (PARTITION BY deptno ORDER BY sal ASC NULLS LAST) AS first_val_in_dept FROM emp; EMPNO DEPTNO SAL FIRST_VAL_IN_DEPT ---------- ---------- ---------- ----------------- 7934 10 1300 1300 7782 10 2450 1300 7839 10 5000 1300 7369 20 800 800 7876 20 1100 800 7566 20 2975 800 7788 20 3000 800 7902 20 3000 800 7900 30 950 950 7654 30 1250 950 7521 30 1250 950 7844 30 1500 950 7499 30 1600 950 7698 30 2850 950 SQL> In this case the "
ASC NULLS LAST" keywords are unnecessary as ASC is the default for an order_by_clause and NULLS LAST is the default for ASC orders. When ordering by DESC, the default is NULLS FIRST.It is important to understand how the
order_by_clause affects display order. The order_by_clause
 is guaranteed to affect the order of the rows as they are processed by 
the analytic function, but it may not always affect the display order. 
As a result, you must always use a conventional ORDER BY 
clause in the query if display order is important. Do not rely on any 
implicit ordering done by the analytic function. Remember, the 
conventional ORDER BY clause is performed after the analytic processing, so it will always take precedence.windowing_clause
We have seen previously thequery_partition_clause controls the window, or group of rows, the analytic operates on. The windowing_clause gives some analytic functions a further degree of control over this window within the current partition. The windowing_clause is an extension of the order_by_clause and as such, it can only be used if an order_by_clause is present. The windowing_clause has two basic forms.RANGE BETWEEN start_point AND end_point ROWS BETWEEN start_point AND end_point
No comments:
Post a Comment