Top Banner

of 28

Analytic Functions by Example

Apr 06, 2018

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • 8/2/2019 Analytic Functions by Example

    1/28

    Analytic functions by ExampleSubmitted by Shouvik Basu on Mon, 2004-11-15 00:00

    y SQL & PL/SQL

    This article provides a clear, thorough concept of analytic functions and its various options by a series ofsimple yet concept building examples. The article is intended for SQL coders, who for might be not be usinganalytic functions due to unfamiliarity with its cryptic syntax or uncertainty about its logic of operation.Often I see that people tend to reinvent the feature provided by analytic functions by native join and sub-query SQL. This article assumes familiarity with basic Oracle SQL, sub-query, join and group function fromthe reader. Based on that familiarity, it builds the concept of analytic functions through a series ofexamples.

    It is true that whatever an analytic function does can be done by native SQL, with join and sub-queries. Butthe same routine done by analytic function is always faster, or at least as fast, when compared to nativeSQL. Moreover, I am not considering here the amount of time that is spent in coding the native SQLs, testing,debugging and tuning them.

    The general syntax of analytic function is:

    Function(arg1,..., argn) OVER ( [PARTITION BY ] [ORDER BY ] [] )

    is like "ROW " or "RANK "All the keywords will be dealt in details as we walk through the examples. The script for creating theschema (SCOTT) on which the example queries of this article are run can be obtained inORACLE_HOME/sqlplus/demo/demobld.sql of any standard Oracle installation.

    How are analytic functions different from group or aggregatefunctions?

    SELECT deptno,

    COUNT(*) DEPT_COUNT

    FROM emp

    WHERE deptno IN (20, 30)

    GROUP BY deptno;

    DEPTNO DEPT_COUNT

    ---------------------- ----------------------

    20 5

    30 6

    2 rows selected

    Query-1

  • 8/2/2019 Analytic Functions by Example

    2/28

    Consider the Query-1 and its result. Query-1 returns departments and their employee count. Mostimportantly it groups the records into departments in accordance with the GROUP BY clause. As such anynon-"group by" column is not allowed in the select clause.

    SELECT empno, deptno,

    COUNT(*) OVER (PARTITION BY

    deptno) DEPT_COUNT

    FROM emp

    WHERE deptno IN (20, 30);

    EMPNO DEPTNO DEPT_COUNT

    ---------- ---------- ----------

    7369 20 5

    7566 20 5

    7788 20 5

    7902 20 5

    7876 20 5

    7499 30 6

    7900 30 6

    7844 30 6

    7698 30 6

    7654 30 6

    7521 30 6

    11 rows selected.

    Query-2Now consider the analytic function query (Query-2) and its result. Note the repeating values of DEPT_COUNTcolumn.

    This brings out the main difference between aggregate and analytic functions. Though analytic functionsgive aggregate result they do not group the result set. They return the group value multiple times with eachrecord. As such any other non-"group by" column or expression can be present in the select clause, forexample, the column EMPNO in Query-2.

    Analytic functions are computed after all joins, WHERE clause, GROUP BY and HAVING are computed on thequery. The main ORDER BY clause of the query operates after the analytic functions. So analytic functionscan only appear in the select list and in the main ORDER BY clause of the query.

    In absence of any PARTITION or inside the OVER( ) portion, the function acts on entirerecord set returned by the where clause. Note the results of Query-3 and compare it with the result ofaggregate function query Query-4.

  • 8/2/2019 Analytic Functions by Example

    3/28

    SELECT empno, deptno,

    COUNT(*) OVER ( ) CNT

    FROM emp

    WHERE deptno IN (10, 20)

    ORDER BY 2, 1;

    EMPNO DEPTNO CNT

    ---------- ---------- ----------

    7782 10 8

    7839 10 8

    7934 10 8

    7369 20 8

    7566 20 8

    7788 20 8

    7876 20 8

    7902 20 8

    Query-3

    SELECT COUNT(*) FROM emp

    WHERE deptno IN (10, 20);

    COUNT(*)

    ----------

    8

    Query-4

    How to break the result set in groups or partitions?It might be obvious from the previous example that the clause PARTITION BY is used to break the result setinto groups. PARTITION BY can take any non-analytic SQL expression.

    Some functions support the inside the partition to further limit the records they act on. Inthe absence of any analytic functions are computed on all the records of the partitionclause.

    The functions SUM, COUNT, AVG, MIN, MAX are the common analytic functions the result of which does notdepend on the order of the records.

    Functions like LEAD, LAG, RANK, DENSE_RANK, ROW_NUMBER, FIRST, FIRST VALUE, LAST, LAST VALUEdepends on order of records. In the next example we will see how to specify that.

    How to specify the order of the records in the partition?

  • 8/2/2019 Analytic Functions by Example

    4/28

    The answer is simple, by the "ORDER BY" clause inside the OVER( ) clause. This is different from the ORDERBY clause of the main query which comes after WHERE. In this section we go ahead and introduce each ofthe very useful functions LEAD, LAG, RANK, DENSE_RANK, ROW_NUMBER, FIRST, FIRST VALUE, LAST, LASTVALUE and show how each depend on the order of the record.

    The general syntax of specifying the ORDER BY clause in analytic function is:

    ORDER BY [ASC or DESC] NULLS [FIRST or LAST]

    The syntax is self-explanatory.

    ROW_NUMBER,RANKand DENSE_RANKAll the above three functions assign integer values to the rows depending on their order. That is the reasonof clubbing them together.

    ROW_NUMBER( ) gives a running serial number to a partition of records. It is very useful in reporting,especially in places where different partitions have their own serial numbers. In Query-5, the functionROW_NUMBER( ) is used to give separate sets of running serial to employees of departments 10 and 20 basedon their HIREDATE.

    SELECT empno, deptno, hiredate,

    ROW_NUMBER( ) OVER (PARTITION BY

    deptno ORDER BY hiredate

    NULLS LAST) SRLNO

    FROM emp

    WHERE deptno IN (10, 20)

    ORDER BY deptno, SRLNO;

    EMPNO DEPTNO HIREDATE SRLNO

    ------ ------- --------- ----------

    7782 10 09-JUN-81 1

    7839 10 17-NOV-81 2

    7934 10 23-JAN-82 3

    7369 20 17-DEC-80 1

    7566 20 02-APR-81 2

    7902 20 03-DEC-81 3

    7788 20 09-DEC-82 4

    7876 20 12-JAN-83 5

    8 rows selected.

    Query-5 (ROW_NUMBERexample)

  • 8/2/2019 Analytic Functions by Example

    5/28

    RANK and DENSE_RANK both provide rank to the records based on some column value or expression. In caseof a tie of 2 records at position N, RANK declares 2 positions N and skips position N+1 and gives position N+2to the next record. While DENSE_RANK declares 2 positions N but does not skip position N+1.

    Query-6 shows the usage of both RANK and DENSE_RANK. For DEPTNO 20 there are two contenders for thefirst position (EMPNO 7788 and 7902). Both RANK and DENSE_RANK declares them as joint toppers. RANKskips the next value that is 2 and next employee EMPNO 7566 is given the position 3. For DENSE_RANK thereare no such gaps.

    SELECT empno, deptno, sal,

    RANK() OVER (PARTITION BY deptno

    ORDER BY sal DESC NULLS LAST) RANK,

    DENSE_RANK() OVER (PARTITION BY

    deptno ORDER BY sal DESC NULLS

    LAST) DENSE_RANK

    FROM emp

    WHERE deptno IN (10, 20)

    ORDER BY 2, RANK;

    EMPNO DEPTNO SAL RANK DENSE_RANK

    ------ ------- ----- ----- ----------

    7839 10 5000 1 1

    7782 10 2450 2 2

    7934 10 1300 3 3

    7788 20 3000 1 1

    7902 20 3000 1 1

    7566 20 2975 3 2

    7876 20 1100 4 3

    7369 20 800 5 4

    8 rows selected.

    Query-6 (RANKand DENSE_RANKexample)

    LEAD and LAGLEAD has the ability to compute an expression on the next rows (rows which are going to come after thecurrent row) and return the value to the current row. The general syntax of LEAD is shown below:

    LEAD (, , ) OVER ()

    is the expression to compute from the leading row. is the index of the leading row relative to the current row.

  • 8/2/2019 Analytic Functions by Example

    6/28

    is a positive integer with default 1. is the value to return if the points to a row outside the partition range.

    The syntax of LAG is similar except that the offset for LAG goes into the previous rows.Query-7 and its result show simple usage of LAG and LEAD function.

    SELECT deptno, empno, sal,

    LEAD(sal, 1, 0) OVER (PARTITION BY dept ORDER BY sal DESC NULLS LAST) NEXT_LOWER_SAL,

    LAG(sal, 1, 0) OVER (PARTITION BY dept ORDER BY sal DESC NULLS LAST) PREV_HIGHER_SAL

    FROM emp

    WHERE deptno IN (10, 20)

    ORDER BY deptno, sal DESC;

    DEPTNO EMPNO SAL NEXT_LOWER_SAL PREV_HIGHER_SAL

    ------- ------ ----- -------------- ---------------

    10 7839 5000 2450 0

    10 7782 2450 1300 5000

    10 7934 1300 0 2450

    20 7788 3000 3000 0

    20 7902 3000 2975 3000

    20 7566 2975 1100 3000

    20 7876 1100 800 2975

    20 7369 800 0 1100

    8 rows selected.

    Query-7 (LEAD and LAG)

    FIRST VALUE and LAST VALUE functionThe general syntax is:

    FIRST_VALUE() OVER ()

    The FIRST_VALUE analytic function picks the first record from the partition after doing the ORDER BY. The is computed on the columns of this first record and results are returned. The LAST_VALUE

    function is used in similar context except that it acts on the last record of the partition.

    -- How many days after the first hire of each department were the next

    -- employees hired?

    SELECT empno, deptno, hiredate ? FIRST_VALUE(hiredate)

  • 8/2/2019 Analytic Functions by Example

    7/28

    OVER (PARTITION BY deptno ORDER BY hiredate) DAY_GAP

    FROM emp

    WHERE deptno IN (20, 30)

    ORDER BY deptno, DAY_GAP;

    EMPNO DEPTNO DAY_GAP

    ---------- ---------- ----------

    7369 20 0

    7566 20 106

    7902 20 351

    7788 20 722

    7876 20 756

    7499 30 0

    7521 30 2

    7698 30 70

    7844 30 200

    7654 30 220

    7900 30 286

    11 rows selected.

    Query-8 (FIRST_VALUE)

    FIRST and LAST functionThe FIRST function (or more properly KEEP FIRST function) is used in a very special situation. Suppose werank a group of record and found several records in the first rank. Now we want to apply an aggregatefunction on the records of the first rank. KEEP FIRST enables that.

    The general syntax is:

    Function( ) KEEP (DENSE_RANK FIRST ORDER BY ) OVER ()

    Please note that FIRST and LAST are the only functions that deviate from the general syntax of analyticfunctions. They do not have the ORDER BY inside the OVER clause. Neither do they support any clause. The ranking done in FIRST and LAST is always DENSE_RANK. The query below shows the usage of

    FIRST function. The LAST function is used in similar context to perform computations on last ranked records.

    -- How each employee's salary compare with the average salary of the first

    -- year hires of their department?

    SELECT empno, deptno, TO_CHAR(hiredate,'YYYY') HIRE_YR, sal,

  • 8/2/2019 Analytic Functions by Example

    8/28

    TRUNC(

    AVG(sal) KEEP (DENSE_RANK FIRST

    ORDER BY TO_CHAR(hiredate,'YYYY') )

    OVER (PARTITION BY deptno)

    ) AVG_SAL_YR1_HIRE

    FROM emp

    WHERE deptno IN (20, 10)

    ORDER BY deptno, empno, HIRE_YR;

    EMPNO DEPTNO HIRE SAL AVG_SAL_YR1_HIRE

    ---------- ---------- ---- ---------- ----------------

    7782 10 1981 2450 3725

    7839 10 1981 5000 3725

    7934 10 1982 1300 3725

    7369 20 1980 800 800

    7566 20 1981 2975 800

    7788 20 1982 3000 800

    7876 20 1983 1100 800

    7902 20 1981 3000 800

    8 rows selected.

    Query-9 (KEEP FIRST)

    How to specify the Window clause (ROW type or RANGE typewindows)?Some analytic functions (AVG, COUNT, FIRST_VALUE, LAST_VALUE, MAX, MIN and SUM among the ones wediscussed) can take a window clause to further sub-partition the result and apply the analytic function. Animportant feature of the windowing clause is that it is dynamic in nature.

    The general syntax of the is

    [ROW or RANGE] BETWEEN AND

    can be any one of the following

    1. UNBOUNDED PECEDING2. CURRENT ROW3. PRECEDING or FOLLOWING.

    can be any one of the following

    1. UNBOUNDED FOLLOWING or

  • 8/2/2019 Analytic Functions by Example

    9/28

    2. CURRENT ROW or3. PRECEDING or FOLLOWING.

    For ROW type windows the definition is in terms of row numbers before or after the current row. So for ROWtype windows must evaluate to a positive integer.

    For RANGE type windows the definition is in terms of values before or after the current ORDER. We will takethis up in details latter.

    The ROW or RANGE window cannot appear together in one OVER clause. The window clause is defined interms of the current row. But may or may not include the current row. The start point of the window andthe end point of the window can finish before the current row or after the current row. Only start pointcannot come after the end point of the window. In case any point of the window is undefined the default isUNBOUNDED PRECEDING for and UNBOUNDED FOLLOWING for .

    If the end point is the current row, syntax only in terms of the start point can be can be[ROW or RANGE] [ PRECEDING or UNBOUNDED PRECEDING ]

    [ROW or RANGE] CURRENT ROW is also allowed but this is redundant. In this case the function behaves as a

    single-row function and acts only on the current row.

    ROWType WindowsFor analytic functions with ROW type windows, the general syntax is:

    Function( ) OVER(PARTITINBY ORDERBY ROWSBETWEEN AND)orFunction( ) OVER(PARTITONBY ORDERBY ROWS [ PRECEDING orUNBOUNDED PRECEDING]

    For ROW type windows the windowing clause is in terms of record numbers.

    The query Query-10 has no apparent real life description (except column FROM_PU_C) but the variouswindowing clause are illustrated by a COUNT(*) function. The count simply shows the number of rows insidethe window definition. Note the build up of the count for each column for the YEAR 1981.

    The column FROM_P3_TO_F1 shows an example where start point of the window is before the current rowand end point of the window is after current row. This is a 5 row window; it shows values less than 5 duringthe beginning and end.

    -- The query below has no apparent real life description (except

    -- column FROM_PU_C) but is remarkable in illustrating the various windowing

    -- clause by a COUNT(*) function.

    SELECT empno, deptno, TO_CHAR(hiredate, 'YYYY') YEAR,

    COUNT(*) OVER (PARTITION BY TO_CHAR(hiredate, 'YYYY')

    ORDER BY hiredate ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM_P3_TO_F1,

    COUNT(*) OVER (PARTITION BY TO_CHAR(hiredate, 'YYYY')

  • 8/2/2019 Analytic Functions by Example

    10/28

    ORDER BY hiredate ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM_PU_TO_C,

    COUNT(*) OVER (PARTITION BY TO_CHAR(hiredate, 'YYYY')

    ORDER BY hiredate ROWS BETWEEN 3 PRECEDING AND 1 PRECEDING) FROM_P2_TO_P1,

    COUNT(*) OVER (PARTITION BY TO_CHAR(hiredate, 'YYYY')

    ORDER BY hiredate ROWS BETWEEN 1 FOLLOWING AND 3 FOLLOWING) FROM_F1_TO_F3

    FROM emp

    ORDEDR BY hiredate

    EMPNO DEPTNO YEAR FROM_P3_TO_F1 FROM_PU_TO_C FROM_P2_TO_P1 FROM_F1_TO_F3

    ------ ------- ---- ------------- ------------ ------------- -------------

    7369 20 1980 1 1 0 0

    7499 30 1981 2 1 0 3

    7521 30 1981 3 2 1 3

    7566 20 1981 4 3 2 3

    7698 30 1981 5 4 3 3

    7782 10 1981 5 5 3 3

    7844 30 1981 5 6 3 3

    7654 30 1981 5 7 3 3

    7839 10 1981 5 8 3 2

    7900 30 1981 5 9 3 1

    7902 20 1981 4 10 3 0

    7934 10 1982 2 1 0 1

    7788 20 1982 2 2 1 0

    7876 20 1983 1 1 0 0

    14 rows selected.

    Query-10 (ROW type windowing example)The column FROM_PU_TO_CURR shows an example where start point of the window is before the currentrow and end point of the window is the current row. This column only has some real world significance. Itcan be thought of as the yearly employee build-up of the organization as each employee is getting hired.

    The column FROM_P2_TO_P1 shows an example where start point of the window is before the current rowand end point of the window is before the current row. This is a 3 row window and the count remainsconstant after it has got 3 previous rows.

    The column FROM_F1_TO_F3 shows an example where start point of the window is after the current row andend point of the window is after the current row. This is a reverse of the previous column. Note how thecount declines during the end.

  • 8/2/2019 Analytic Functions by Example

    11/28

    RANGE WindowsFor RANGE windows the general syntax is same as that of ROW:

    Function( ) OVER (PARTITION BY ORDER BY RANGE BETWEEN AND)or

    Function( ) OVER (PARTITION BY ORDER BY RANGE [ PRECEDING orUNBOUNDED PRECEDING]

    For or we can use UNBOUNDED PECEDING, CURRENT ROW or PRECEDING or FOLLOWING. However for RANGE type windows must evaluate to value compatiblewith ORDER BY expression .

    is a logical offset. It must be a constant or expression that evaluates to a positive numeric valueor an interval literal. Only one ORDER BY expression is allowed.

    If evaluates to a numeric value, then the ORDER BY expr must be a NUMBER or DATE datatype. If evaluates to an interval value, then the ORDER BY expr must be a DATE datatype.

    Note the example (Query-11) below which uses RANGE windowing. The important thing here is that the sizeof the window in terms of the number of records can vary.

    -- For each employee give the count of employees getting half more that their

    -- salary and also the count of employees in the departments 20 and 30 getting half

    -- less than their salary.

    SELECT deptno, empno, sal,

    Count(*) OVER (PARTITION BY deptno ORDER BY sal RANGE

    BETWEEN UNBOUNDED PRECEDING AND (sal/2) PRECEDING) CNT_LT_HALF,

    COUNT(*) OVER (PARTITION BY deptno ORDER BY sal RANGE

    BETWEEN (sal/2) FOLLOWING AND UNBOUNDED FOLLOWING) CNT_MT_HALF

    FROM emp

    WHERE deptno IN (20, 30)

    ORDER BY deptno, sal

    DEPTNO EMPNO SAL CNT_LT_HALF CNT_MT_HALF

    ------- ------ ----- ----------- -----------

    20 7369 800 0 3

    20 7876 1100 0 3

    20 7566 2975 2 0

    20 7788 3000 2 0

    20 7902 3000 2 0

  • 8/2/2019 Analytic Functions by Example

    12/28

    30 7900 950 0 3

    30 7521 1250 0 1

    30 7654 1250 0 1

    30 7844 1500 0 1

    30 7499 1600 0 1

    30 7698 2850 3 0

    11 rows selected.

    Query-11 (RANGE type windowing example)

    Order of computation and performance tipsDefining the PARTITOIN BY and ORDER BY clauses on indexed columns (ordered in accordance with thePARTITION CLAUSE and then the ORDER BY clause in analytic function) will provide optimum performance.For Query-5, for example, a composite index on (deptno, hiredate) columns will prove effective.

    It is advisable to always use CBO for queries using analytic functions. The tables and indexes should beanalyzed and optimizer mode should be CHOOSE.

    Even in absence of indexes analytic functions provide acceptable performance but need to do sorting forcomputing partition and order by clause. If the query contains multiple analytic functions, sorting andpartitioning on two different columns should be avoided if they are both not indexed.

    ConclusionThe aim of this article is not to make the reader try analytic functions forcibly in every other complex SQL.It is meant for a SQL coder, who has been avoiding analytic functions till now, even in complex analyticqueries and reinventing the same feature much painstakingly by native SQL and join query. Its job is done ifsuch a person finds analytic functions clear, understandable and usable after going through the article, and

    starts using them.

    y Shouvik Basu's blogy Login to post comments

    Submitted by Stephen (not verified) on Fri, 2005-08-26 06:14.

    Most of the examples that I have come across deal with simple dates. What aboutwhen you have a data set that contains records with timestamps and you would like toroll them up to the second and then look at a sliding window to find, say the busiest 5minutes of the day? It is trivial to create the query to aggregate the data into per-

    second blocks but I cannot figure out the syntax to put a window around it.

    Thanks.

    y Login to post comments

  • 8/2/2019 Analytic Functions by Example

    13/28

    useful topicSubmitted by abuleen on Mon, 2009-01-12 04:28.

    This is very useful topic,But I have simple problem I can not solve,I want the id(or any column) of the row before the current row?

    y Login to post commentsdynamic window rangeSubmitted by Veslar on Thu, 2010-09-16 01:58.

    Hi Stephen,

    try this > > >

    create table trt (timepoint timestamp,random_str varchar2(7));

    insert into trt values(to_timestamp('16.09.2010 07:05:51:781000','DD.MM.YYYYHH24:MI:SS:FF6'),'piNX');insert into trt values(to_timestamp('16.09.2010 07:09:11:453000','DD.MM.YYYYHH24:MI:SS:FF6'),'EKzU');insert into trt values(to_timestamp('16.09.2010 07:09:16:515000','DD.MM.YYYYHH24:MI:SS:FF6'),'rnZg');insert into trt values(to_timestamp('16.09.2010 07:09:18:890000','DD.MM.YYYYHH24:MI:SS:FF6'),'LFEy');insert into trt values(to_timestamp('16.09.2010 07:09:24:187000','DD.MM.YYYYHH24:MI:SS:FF6'),'BNZf');

    insert into trt values(to_timestamp('16.09.2010 07:09:26:937000','DD.MM.YYYYHH24:MI:SS:FF6'),'FXFD');insert into trt values(to_timestamp('16.09.2010 07:09:29:140000','DD.MM.YYYYHH24:MI:SS:FF6'),'Esgz');insert into trt values(to_timestamp('16.09.2010 07:09:30:921000','DD.MM.YYYYHH24:MI:SS:FF6'),'wolR');insert into trt values(to_timestamp('16.09.2010 07:09:32:218000','DD.MM.YYYYHH24:MI:SS:FF6'),'AijN');insert into trt values(to_timestamp('16.09.2010 07:09:33:500000','DD.MM.YYYYHH24:MI:SS:FF6'),'PUot');insert into trt values(to_timestamp('16.09.2010 07:09:34:625000','DD.MM.YYYY

    HH24:MI:SS:FF6'),'nIUX');insert into trt values(to_timestamp('16.09.2010 07:09:35:796000','DD.MM.YYYYHH24:MI:SS:FF6'),'DGTf');insert into trt values(to_timestamp('16.09.2010 07:09:36:750000','DD.MM.YYYYHH24:MI:SS:FF6'),'eEYe');insert into trt values(to_timestamp('16.09.2010 07:09:37:828000','DD.MM.YYYYHH24:MI:SS:FF6'),'mHYt');insert into trt values(to_timestamp('16.09.2010 07:09:38:859000','DD.MM.YYYY

  • 8/2/2019 Analytic Functions by Example

    14/28

    HH24:MI:SS:FF6'),'buWA');insert into trt values(to_timestamp('16.09.2010 07:09:39:968000','DD.MM.YYYYHH24:MI:SS:FF6'),'yllr');insert into trt values(to_timestamp('16.09.2010 07:09:45:359000','DD.MM.YYYYHH24:MI:SS:FF6'),'WJua');

    insert into trt values(to_timestamp('16.09.2010 07:09:48:328000','DD.MM.YYYYHH24:MI:SS:FF6'),'Zsrp');insert into trt values(to_timestamp('16.09.2010 07:09:50:656000','DD.MM.YYYYHH24:MI:SS:FF6'),'WtDJ');commit;

    SELECT TO_CHAR(timepoint,'DD.MM.YYYY HH24:MI:SS.FF3')"Start_bussiest_5sec_interval"FROM(SELECT timepoint,DENSE_RANK() over (order by forw_dens_per_5sec DESC,end_time_5sec-

    timepoint,timepoint) rankFROM(SELECT timepoint,COUNT(*) over (order by timepoint range BETWEEN CURRENT row AND interval '5'

    second following ) forw_dens_per_5sec,MAX(timepoint) over (order by timepoint range BETWEEN CURRENT row AND

    interval '5' second following ) end_time_5secFROM trt)

    )WHERE rank=1;

    Regards

    Veslar

    y Login to post commentsCorrectionSubmitted by pakkiaraj on Thu, 2010-12-30 03:19.

    The output of your query is: Start_bussiest_5sec_interval=16.09.2010 07:09:35.796. But I guess this is not the starting of the busiest 5 secinterval. I guess it should be = 16.09.2010 07:09:30.921. If I am correct than yourquery should be modifed here:

    DENSE_RANK() over (order by forw_dens_per_5sec DESC,end_time_5sec-timepointDESC,timepoint) rank.

  • 8/2/2019 Analytic Functions by Example

    15/28

    Regards.Pakkia

    y Login to post commentsExplanationSubmitted by Veslar on Sat, 2011-07-02 05:35.

    Try this and you'll see why it is so, as I wrote the first time > > >

    SELECT *FROM(SELECTDENSE_RANK() over (order by forw_dens_per_5sec DESC,end_time_5sec-timepoint,timepoint) rank,s.*,

    end_time_5sec-timepoint dffFROM(SELECT timepoint,COUNT(*) over (order by timepoint range BETWEEN CURRENT row AND interval '5'second following ) forw_dens_per_5sec,MAX(timepoint) over (order by timepoint range BETWEEN CURRENT row AND interval'5' second following ) end_time_5secFROM trt) s)ss--WHERE rank=1

    ;

    The density is 5 records per interval for both (my and your solution) but mine hasminor diff between first member and last one (order by forw_dens_per_5secDESC,end_time_5sec-timepoint,timepoint).

    y Login to post commentsSubmitted by Sateesh (not verified) on Mon, 2005-08-22 13:40.

    When I was stuck with the oracle documentation reading about analytic functions,being described highly formally, I got thisexcellent article describing complex things in really simple terms with examples.

    y Login to post commentsSubmitted by Dwarak (not verified) on Thu, 2005-02-03 18:32.

  • 8/2/2019 Analytic Functions by Example

    16/28

    Hey, why don't u write a book on this.This article is really cool.

    y Login to post commentsSubmitted by Russell (not verified) on Thu, 2005-04-14 17:34.

    I was stuck with some Oracle Analytical function and was looking for some help.Bumped across this article.

    Really neat! Keep up the good work.

    y Login to post commentsSubmitted by bill gfroehrer (not verified) on Tue, 2005-06-14 07:20.

    Hi Shouvik,

    I was dusting off my OLAP stuff (been a while) seeking a solution to a data loadingissue. Your article "Analytic functions by Example" helped me zero in on the solution.

    Gratitude and a "Thousand At-A-Boys" to you.

    Keep up the good work!

    BG...

    y Login to post commentsSubmitted by Luke Curran (not verified) on Wed, 2005-06-08 08:11.

    Excellent article. I personally learn best with simple examples to demonstratepotentially complex concepts ... and this article was perfect. Thanks.

    y Login to post commentsSubmitted by usha (not verified) on Sun, 2005-07-10 21:46.

    Thanx a lot!! This doc really helped me a lot.One can get a clear idea regarding analytical functions if he/she go thru this pageonce..Usha

  • 8/2/2019 Analytic Functions by Example

    17/28

    y Login to post commentsSubmitted by Manoj Pathak (not verified) on Wed, 2005-04-27 14:44.

    Excellent!! it is a great privilege to work with you.

    y Login to post commentsSubmitted by Vadi (not verified) on Fri, 2005-05-06 11:50.

    -- How many days after the first hire of each department were the next employeeshired?SELECT empno, deptno, hiredate ? FIRST_VALUE(hiredate)OVER (PARTITION BY deptno ORDER BY hiredate) DAY_GAPFROM empWHERE deptno IN (20, 30)ORDER BY deptno, DAY_GAP;

    I think there is an error in this query. It does not return the same results as shown inthe example.Thanks in advance

    y Login to post commentscorrectionSubmitted by santoshshinde (not verified) on Fri, 2006-09-22 09:54.

    Quote:

    A great article with everything put together about getting started with analytical

    functions.Regarding correction:

    Replace the '?' with '-'. I think that will give the difference in dates to calculate thedays.

    SELECT empno, deptno, hiredate - FIRST_VALUE(hiredate)

    OVER (PARTITION BY deptno ORDER BY hiredate) DAY_GAP

    FROM emp

    WHERE deptno IN (20, 30)

    ORDER BY deptno, DAY_GAP;

    y Login to post comments

  • 8/2/2019 Analytic Functions by Example

    18/28

    Submitted by Ivor Oorloff (not verified) on Fri, 2005-04-29 04:33.

    I was trying to use the dense_rank function to tune a query but really couldn'tunderstand the Oracle doco - your page helped me make the breakthrough and myquery runs instantly now whereas it took an hour before.

    y Login to post commentsThis is an excellentSubmitted by Karen Sullivan (not verified) on Tue, 2005-10-25 09:23.

    This is an excellent treatment of analytic functions. Other analytic function articlesjust didn't cut it for me. After reading this, was able to quickly solve an SQL problem.

    I've added your URL to our Business Unit's Web Site.

    Thank you.

    y Login to post commentsReally EnthrallingSubmitted by Arindam Mukherjee (not verified) on Tue, 2006-03-21 04:12.

    Hello,

    What a presentation you have had in this web page. I appreciate your intuition andnoble efforts. Looking forward to seeing your article on how to write well-tuned SQL.May GOD bless you!!

    Regards,Arindam Mukherjee

    y Login to post commentsAnalytic Functions - Awesome articleSubmitted by Prakash Rai (not verified) on Sat, 2006-10-07 22:26.

    Shouvik -

    Like many other readers I am your real fan.

    I have been looking to explore the analytic functions and this article with examples isjust a great startup. I won't amaze to Google your name to find something rare gemsabout Oracle.

    Keep up the great work!

  • 8/2/2019 Analytic Functions by Example

    19/28

    Regards,Prakash

    y Login to post commentsAnalytic Functions - GreatSubmitted by B Adhvaryu (not verified) on Fri, 2006-11-24 11:56.

    Shouvik,

    This is one of the best article I have ever found to start up with Analytic Function.

    I would say just keep it up and forward the same related articles.

    Regards,Ba

    y Login to post commentsVery Great Effort - Add more here with timeSubmitted by Aasif (not verified) on Fri, 2006-12-15 00:15.

    This is a really great effort. It helped me a lot to clear my ambiguities. Please addmore in it with the passage of time when you learns/experiences more about thesefunctions.

    Best Regards,Aasif

    y Login to post commentsexecllent effortSubmitted by mirahmad on Fri, 2007-03-09 04:42.

    This is a very good artical for the people who don't know how to use the function foranalytical work.

    y Login to post commentsawesomeSubmitted by kang on Tue, 2008-03-11 23:05.

    awesome.Thanks.

  • 8/2/2019 Analytic Functions by Example

    20/28

    y Login to post commentsis this a bug?Submitted by kang on Wed, 2008-03-12 18:27.

    create table emp (empno varchar2(10),deptno varchar2(10),sal number(10))

    insert into emp(empno,deptno,sal) values('1','10',101);insert into emp(empno,deptno,sal) values('2','20',102);insert into emp(empno,deptno,sal) values('3','20',103);insert into emp(empno,deptno,sal) values('4','10',104);insert into emp(empno,deptno,sal) values('5','30',105);

    insert into emp(empno,deptno,sal) values('6','30',106);insert into emp(empno,deptno,sal) values('7','30',107);insert into emp(empno,deptno,sal) values('8','40',108);insert into emp(empno,deptno,sal) values('9','30',109);insert into emp(empno,deptno,sal) values('10','30',110);insert into emp(empno,deptno,sal) values('11','30',100);

    SELECT empno, deptno, sal,last_value(sal)OVER (PARTITION BY deptno order by sal desc) col1,first_value(sal)

    OVER (PARTITION BY deptno order by sal asc) col2,first_value(sal)OVER (PARTITION BY deptno order by sal desc) col3,last_value(sal)OVER (PARTITION BY deptno order by sal asc) col4FROM emp

    col2, col3 return what I expect.

    I don't know why col1 and col4 return the these kinds of results.

    y Login to post commentsCaveat with LAST_VALUE function (answering Kang's concern)Submitted by shouvikb on Mon, 2008-03-17 23:44.

    If anyone has Metalink Access, read Doc ID 696344.992.

  • 8/2/2019 Analytic Functions by Example

    21/28

    Broadly speaking,All analytic functions with ORDER BY operate on a default window - a subset ofcontiguous rows (according to the analytic ORDER BY clause) within the partition. Thedefault windowing clause is "RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENTROW". This affects the LAST_VALUE.

    To get the results as you want you need to have.(PARTITION BY deptno order by sal desc ROWSBETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING).

    Hope this helps,Shouvik Basu

    y Login to post commentsQuery -11 column CNT_MT_HALFSubmitted by jayesh_nazre on Wed, 2008-03-26 10:12.

    I am finding it hard to understand this can someone explain how its counting the lastcolumnBased on what I understand "CNT_LT_HALF" divides the curron row sal and compareswith precedding sal row values and that looks fine (not the count does not include theexisting row in its count so its less that not less than equal to)however when I try to apply the same for "CNT_MT_HALF" columsay take current rows sal/2 eg. 800/2 = 400now within dept = 20 if you compare this value with all the following sal then for thefirst row "CNT_LT_HALF" column should have a value of "4" and not "3". I ran the queryin Oracle database and the query matches what the article output is ("3"). I know I amunderstanding it wrong, can someone explain

    y Login to post commentsWay to do a running total by date.Submitted by ccheilig on Mon, 2008-10-13 10:24.

    I had a really slow sql query that had columns of effecivedate, amount and runningtotal to date.

    by using analytic function I was able to make a 90 second query a < 2 second querywith following syntax.

    SELECT effectivedate, amount, SUM(amount) OVER (PARTITION BY sysdate ORDER BYeffectivedate)FROM mytableORDER BY effectivedate DESC

  • 8/2/2019 Analytic Functions by Example

    22/28

    I think this little snippet will be useful in many applications.Truly enyoyed your article which gave me the idea to try it this way! Thanks so much!

    y Login to post commentsAnalytic FunctionSubmitted by zhopka on Tue, 2008-11-11 10:20.

    Am I doing something wrong?I have table a and table b, the relation between them is one to many. In table a Ihave column tax, in table b I have unit price and qty, what I need to get by my queryis avg tax, total (sum) tax and sum of price*qty. I have problem with avg_tax_chg anddoc_$_tot when join tables. Can somebody help?select a.doc_num, a.tax_chg,avg(a.tax_chg) over ( ) avg_tax_chg,sum(a.tax_chg) over (partition by a.ord_tp_cd,a.final_dt,a.stat_cd) tot_tax_chg,

    sum(b.qty*b.unit_prc) over (partition by s.del_doc_num) doc_$_totfrom a, bwhere a.doc_num = b.doc_num

    Thanks

    y Login to post commentsRecursive Sum

    Submitted by muratyildiz on Sat, 2008-11-29 20:02.I want to recursevi summary by using analytic functions.How can I do?ThanksFor example:

    A TABLE B TABLE SQL RESULT MUST BECODE CODE VALUES CODE SUM()----- ------------- ------------------------1 10000 200 1 60010 10001 300 10 600

    100 10010 100 100 6001000 2000 200 1000 50010000 10000 20010001 10001 3001001 1001 10010010 10010 1002 2 20020 ....................

  • 8/2/2019 Analytic Functions by Example

    23/28

    2002000....

    y Login to post commentsThis topic is however quiteSubmitted by swainprafullaranjan on Tue, 2008-12-09 03:03.

    This topic is however quite informative and constructive .But there are some explainations in which still abscruity is thereSo in the next topic please try to give the proper and cleare explaination

    y Login to post commentsThis Article is a Model Example of Analytical Writing ClaritySubmitted by harrysmall3 on Fri, 2008-12-19 18:27.

    RE:"This topic is however quite"

    Mr. Swainprafullaranjan, the only obscurity with the text on this page lay within thecontent of your comment. You provide incomplete sentences with the majority ofwords mis-spelled and absolutely no reference to what part of the article text thatyou find unclear or improper .

    Had you written your thoughts truly as just a comment I would have refrained from

    mine. Since you felt obliged to lecture the author on improvement before writingfurther topics, I feel absolutely obliged to provide the same suggestion to you beforecritiquing any future article, post, or comment on this site.

    Shouvic Basu effectively conveyed in his article, completely, what his topic statementintended- to provide ".. a clear, thorough concept of analytic functions and its variousoptions by a series of simple yet concept building examples".

    The flow of his presentation demonstrates a unique ability that I would coin as"precision in detail" of the subject matter. The quantity of detail and selection oforganization in my opinion produced an article of many abilities - readability,

    learnability, capability... and enjoyability - a rare treat in reference material work.

    I believe this view is the shared consensus amongst his readers. I can relate exactly tothe response by Luke Curran: "Excellent article. I personally learn best with simpleexamples to demonstrate potentially complex concepts ... and this article wasperfect. Thanks. "

  • 8/2/2019 Analytic Functions by Example

    24/28

    Shouvic, I appreciate with great admiration your knowledge sharing and look forwardto all future topics that you chose to cover. I have been working extensively withanalytic functions on my current work projects and this article filled in a lot ofbackground for me as well as new areas to further this study.

    As an author of a chess novel myself, there were periods -painstaking times -in mywriting that in retrospect had I posessed the same ability to convey detail as you withsuch precision, I believe that I would not be dyeing as much grey hair today!

    Best Regards,Harry

    y Login to post comments

    Thanks for a Very Useful ArticleSubmitted by Dipali Vithalani on Sat, 2009-01-03 07:21.Hi,

    I decided to learn analytical functions conceptually and luckily I got this article. Itsvery useful. The way of treating the subject is very effective. While reading, I triedthem practically and now I am quite confident about their usage.

    Thanks a lot for such a useful article!

    Regards,Dipali.

    y Login to post commentsIt is very helpfulSubmitted by cpsundar on Fri, 2009-02-27 14:48.

    It gives quick understanding of analytical function.Great work.

    Thanks for your article.

    y Login to post commentsAwesomeSubmitted by holdingbe on Thu, 2009-04-02 08:53.

    Thanks a lot for such a useful article!

  • 8/2/2019 Analytic Functions by Example

    25/28

    y Login to post commentsVery Good OverviewSubmitted by Vackar on Tue, 2009-11-03 08:40.

    That was one of the best articles I've read in terms of how to explain an otherwiserather complicated topic.

    Great work!!

    y Login to post commentsYTD Calculation using analytical functionsSubmitted by tssr_2001 on Thu, 2010-02-04 03:41.

    Hi,

    I am using Oracle Database 10gR1.Please help me to write the following query.

    I want to calculate ytd ( year to date calculation ), then i have to sum up monthlythen sum up for yearly.Eg : I have to calculate YTD as follows :

    GL Curr Day Amount Month YTD5805 45454 1-Jan 5.23 5.23 5.23

    5805 45454 2-Jan -4.52 0.71 5.945805 45454 3-Jan 25.3 26.01 31.955805 45454 4-Jan 10.53 36.54 68.495805 45454 5-Jan -1.88 34.66 103.15

    Here in this example, we have column names as gl, curr, day, amount, month, year ;taken from a 1 transaction table.Now, To calculate ytd (year to-date calculation), i have to calculate month first andthen year.

    Step 1: Month wise summation :

    I have to calculate sum for each day of the month.

    From above example for month wise summation:GL Curr Day Amount Month5805 45454 1-Jan 5.23 5.23 ( sum of jan1 = 5.23 )5805 45454 2-Jan -4.52 0.71 ( sum of jan2 = 5.23 + (-4.52) = 0.71 )5805 45454 3-Jan 25.3 26.01 ( sum of jan3 = 0.71 + 25.3 = 26.01 )

  • 8/2/2019 Analytic Functions by Example

    26/28

    5805 45454 4-Jan 10.53 36.54 ( sum of jan4 = 26.01 + 10.53 = 36.54 )5805 45454 5-Jan -1.88 34.66 ( sum of jan4 = 36.54 + (-1.88) = 34.66 )

    Step 2: Year wise summation : YTD Calculation :We have done Step1 process to calculate this Step2 process, i.e., YTD Calculation.

    So, we have to do Year wise summation with the Step1 month wise data ( with theabove output date ).

    Again, from above example for year wise summation:GL Curr Day Amount Month YTD5805 45454 1-Jan 5.23 5.23 5.23 ( ytd = 5.23 )5805 45454 2-Jan -4.52 0.71 5.94 ( ytd = 5.23 + 0.71 = 5.94)5805 45454 3-Jan 25.3 26.01 31.95 ( ytd = 5.94 + 26.01 = 31.95 )5805 45454 4-Jan 10.53 36.54 68.49 ( ytd = 31.95 + 36.54 = 68.49 )5805 45454 5-Jan -1.88 34.66 103.15 ( ytd = 68.49 + 34.66 = 103.15 )

    So for year to-date calculation, we have to sum all the dates for a month and thensum all the month to get ytd.How can i do this ytd using any analytical functions (i.e., i have to sum up for everyrow) ?

    Thanks.

    y Login to post comments

    answer to tssr_2001Submitted by pakkiaraj on Thu, 2010-12-30 00:46.Hi,

    select b.*,sum(month) over(partition by GL order by day) YEAR from (selectgl,curr,day,amount,sum(amount) over(partition by GL order by day) month fromtemp1_p ) b.

    This article is very nice. HatZ off to ORAFAQ!

    y Login to post commentsGood explanation of Analytical FunctionsSubmitted by bhavin_rudani on Sat, 2010-02-20 04:41.

    Thanks for the details on Analytical Functions

  • 8/2/2019 Analytic Functions by Example

    27/28

    y Login to post commentsGreat teacher!Submitted by sadenwala on Fri, 2010-03-26 12:32.

    With 16 years of Oracle experience, I would just stay away from "partion by" and"over" clause, because I never really understood what it did. Your article is an eyeopener for me. Yeah, promise I will buy your book if you write one!!

    THANK YOU!!

    y Login to post commentsThanks for the PostSubmitted by panyamravi on Tue, 2010-03-30 08:08.

    It's nice to see a detailed explanation about the Analytical Functions by considering

    our old "EMP" database as the source.

    y Login to post commentsGood Article on analytical functionsSubmitted by shivakrishnas on Fri, 2010-06-25 06:09.

    Thank you for giving clear explanation about analytical functions. Very useful.

    y Login to post commentsVery good article for analytical functionsSubmitted by prashantgauda on Mon, 2010-11-15 03:23.

    Yesterday, I was dealing with some of the queries asked by my brother which I findvery cumbersome with group by and long query.

    I searched for analytical functions and believe me the content in your post is so easyto understand that I quickly solved his query and protected my image of knowing a bitmore than him. :)

    Anyway, I have suggested him to stick to your examples for basic understanding.

    Thanks for very good post.

    Thanks,Prashant Gauda

  • 8/2/2019 Analytic Functions by Example

    28/28

    y Login to post commentswha are analytic functions different from group or aggregate funSubmitted by ramth85 on Mon, 2010-11-22 03:13.

    Fine answer!

    y Login to post commentsThank you very much...Submitted by gknauss on Mon, 2011-11-28 07:33.

    I came across this article back in 2009 and printed it out (wanted to make sure that ifthe post was ever removed, I would still this vital information). I have referred backto these examples many times as a reference, they have helped me numerous times insolving a problem. Just wanted to let you know that an article you wrote in 2004 isstill being used today. Thank you.

    y Login to post commentsKindly clear me about the rows and ranges, please?Submitted by seetha_ta on Tue, 2011-12-27 05:39.

    Hi

    Its very easy to follow your article.But i am not aware about the concept ROWS AND RANGE.In your example what does the "3 PRECEDING AND 1 FOLLOWING" refers and how itworks in the below syntax ? I tried lot to get it, but in vain.Kindly clear me about it. It will be very helpfull

    SELECT empno, deptno, TO_CHAR(hiredate, 'YYYY') YEAR,COUNT(*) OVER (PARTITION BY TO_CHAR(hiredate, 'YYYY')ORDER BY hiredate ROWS BETWEEN 3 PRECEDING AND 1 FOLLOWING) FROM_P3_TO_F1FROM empORDEDR BY hiredate

    y Login to post comments