Analytical functions: FIRST vs FIRST_VALUE

Hello

Can someone please help me understand the difference between PRIME and FIRST_VALUE in Anaytic functions.

I tried below 2 queries, but I see the same output. The only difference I see is that the field of the SAL is ordered FIRST_VALUE, but not the FIRST.

SELECT ename,

DEPTNO,

SAL,

MIN (SAL) keep (dense_rank FIRST

ORDER BY sal) by (deptno partition) FIRST

EMP;

SELECT ename,

DEPTNO,

SAL,

FIRST_VALUE (SAL) over (partition BY deptno arrested by sal) FIRST

EMP;

With the help of: Windows 8.1

Database Oracle 12 c Enterprise Edition Release 12.1.0.1.0 - 64 bit Production

PL/SQL Release 12.1.0.1.0 - Production

"CORE 12.1.0.1.0 Production."

AMT for 64-bit Windows: Version 12.1.0.1.0 - Production

NLSRTL Version 12.1.0.1.0 - Production

Hello

Here is an example of when you can use the FIRST analytic function.

Say you want the average sal for each Department, but only for the first year (taken from the hiredate column) in the Department (i.e., the column called f in the query below).

WITH got_hireyear AS

(

SELECT deptno and ename, sal, hiredate

EXTRACT (YEAR FROM hiredate) AS hireyear

FROM scott.emp

)

SELECT deptno, hireyear, hiredate, ename, sal

AVG (sal) DUNGEON (DENSE_RANK FIRST ORDER BY hireyear)

COURSES (PARTITION BY deptno

) In the FORM f

FIRST_VALUE (sal) over (PARTITION BY deptno

ORDER BY hireyear

) AS fv

AVG (sal) over (PARTITION BY deptno

hireyear

), A

OF got_hireyear

ORDER BY deptno

hireyear

ename

;

Output:

HIREYEAR ENAME SAL HIREDATE DEPTNO F FV HAS
------ ---------- ----------- ---------- ------ --------- ------ ---------
10 1981 9 June 1981 CLARK 2450 2450 3725,00 3725.00
10 1981 17 November 1981 KING 5000 3725,00 2450 3725.00
10 1982 23 January 1982 MILLER 1300 3725,00 2450 1300.00

20, 1980, 17 December 1980 SMITH 800 800.00 800.00 800
20, 1981, 3 December 1981 FORD 3000 800.00 800 2987.50
20, 1981, 2 April 1981 JONES 2975 800.00 800 2987.50
20, 1987, 23 May 1987 ADAMS 1100 800.00 800 2050.00
20, 1987, 19 April 1987 SCOTT 3000 800.00 800 2050.00

30 1981 20 February 1981 ALLEN 1600 1566.67 950 1566.67
May 30 1981 1st 1981 BLAKE 2850 1566.67 950 1566.67
December 30 1981 3 1981 JAMES 950 1566.67 950 1566.67
30 1981 28 - sep - 1981 MARTIN 1250 1566.67 950 1566.67
30-08 - sep - 1981 1981 TURNER 1500 1566.67 950 1566.67
30 1981 22 February 1981 WARD 1250 1566.67 950 1566.67

The analytical FIRST_VALUE function can do (except in the very special case where only 1 row has the lowest hireyear, as in deptno = 20).  AVG analysis can do (except in the very special case that all lines have the same hireyear as in deptno = 30).

Tags: Database

Similar Questions

  • FIRST_VALUE() and LAST_VALUE Analytic Functions

    Hi all

    May be that it is a fundamental issue. But I'm having a hard time understanding the difference between FIRST_VALUE() and LAST_VALUE() of analytical functions.

    As much as what I read the FIRST_VALUE function picks up the first record after the partition and order by and he returned after all calculation. And the LAST_VALUE does the opposite. But the result of the second query as I expected, are not (last value of the partition). It would be useful that someone could throw some light on it.
    select empno
         , ename
         , sal
         , first_value(ename) over(order by sal desc)
      from emp;
    
    empno  ename      sal       first_value 
    ------ ---------- --------- ----------- 
    7839   KING       5000.00   KING        
    7902   FORD       3000.00   KING        
    7788   SCOTT      3000.00   KING        
    7566   JONES      2975.00   KING        
    7698   BLAKE      2850.00   KING        
    7782   CLARK      2450.00   KING        
    7499   ALLEN      1600.00   KING        
    7844   TURNER     1500.00   KING        
    7934   MILLER     1300.00   KING        
    7654   MARTIN     1250.00   KING        
    7521   WARD       1250.00   KING        
    7876   ADAMS      1100.00   KING        
    7900   JAMES      950.00    KING        
    7369   SMITH      800.00    KING        
    
    14 Row(s) affected
    select empno
         , ename
         , sal
         , last_value(ename) over(order by sal desc)
      from emp;
    
    empno  ename      sal       last_value 
    ------ ---------- --------- ---------- 
    7839   KING       5000.00   KING       
    7902   FORD       3000.00   SCOTT      
    7788   SCOTT      3000.00   SCOTT      
    7566   JONES      2975.00   JONES      
    7698   BLAKE      2850.00   BLAKE      
    7782   CLARK      2450.00   CLARK      
    7499   ALLEN      1600.00   ALLEN      
    7844   TURNER     1500.00   TURNER     
    7934   MILLER     1300.00   MILLER     
    7521   WARD       1250.00   MARTIN     
    7654   MARTIN     1250.00   MARTIN     
    7876   ADAMS      1100.00   ADAMS      
    7900   JAMES      950.00    JAMES      
    7369   SMITH      800.00    SMITH      
    
    14 Row(s) affected
    Thank you
    Vincent

    Hey, Vincent,.

    When you use an analytic function with an ORDER BY clause, the results will be based on a window, which is a subset of the partition.
    If you do not specify a window (using the keywords LINE or LINES) the window everything will be in order by the ORDER BY clause, until and including the current line, including links.

    For example, in your second query:

    select empno
         , ename
         , sal
         , last_value(ename) over(order by sal desc)
      from emp;
    
    empno  ename      sal       last_value
    ------ ---------- --------- ----------
    7839   KING       5000.00   KING
    7902   FORD       3000.00   SCOTT
    7788   SCOTT      3000.00   SCOTT
    7566   JONES      2975.00   JONES
    7698   BLAKE      2850.00   BLAKE
    7782   CLARK      2450.00   CLARK
    7499   ALLEN      1600.00   ALLEN
    7844   TURNER     1500.00   TURNER
    7934   MILLER     1300.00   MILLER
    7521   WARD       1250.00   MARTIN
    7654   MARTIN     1250.00   MARTIN
    7876   ADAMS      1100.00   ADAMS
    7900   JAMES      950.00    JAMES
    7369   SMITH      800.00    SMITH    
    

    The analytic function

    last_value(ename) over(order by sal desc)
    

    Returns the last ename, not of the entire table, but the window starting with the highest sal (since you say "ORDER BY sal DESC") and including the current line and all the other lines that have the same sal.

    So consider the 1st row, ename = 'KING '. It has the most sal, so that a single line in the window, 'KING' IS THE LAST VALUE WINDOW.

    Now consider the 2nd row, where ename = 'FORD' and sal = 3000. The window includes now everybody with a sal of 3000 and more, which means the 3 rows 'KING', 'FORD' and 'SCOTT '. The last of them (in descending order of sal) is 'SCOTT '. (In fact, there is a tie, you could just as well say that "JONES" is changed, because there is a tie between the two rows where sal = 3000) When this happens, one of the lines will arbitrarily designate the "last" line don't expect not to be always the same line.)

    Because of this, LAST_VALUE is alwmost always used with an explicit windowing clause, beginning with the BEACH or LINES.

    If you want a request as your first request, but it contains the name of the lowest paid employee (that is, he always says 'SMITH' in the last column instead of 'KING'), then use FIRST_VALUE, but reverse the sort order:

    first_value(ename) over(order by sal ASC)
    
  • Return one row of an analytic function

    Hello

    I pulled the following query:

    Select ID_STORNO, first_value (COD_CONTATTO) ON (Partition of COD_CONTATTO

    order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT

    rows between unbounded preceding and following unbounded)

    as COD_CONTATTO_LAST

    of WT_STR_ESG_CONTATTO;

    The result is:

    2160603C1-H83J1N
    2160603C8-9FOHXJS
    2258072C1-H83J1N

    But I just need to take the following lines

    2160603C8-9FOHXJS
    2258072C1-H83J1N

    Because for the same value of ID_STORNO, I just need to get a value of COD_CONTATTO (to select the best value using COD_PRIORITY and FT_DAT_OPEN_CNT). What is wrong inside the query? I just use 2 or 3 times the oracle analytic functions.

    Best regards

    As SomeoneElse... you need a where clause clause in order to choose the ones you want.

    To do this, the typical is to select a column that you use for this reason, such as:

    "I want to just the first record in each group..."

    Select id_storno, cod_contatto_last from)

    Select ID_STORNO, first_value (COD_CONTATTO) ON (Partition of COD_CONTATTO

    order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT

    rows between unbounded preceding and following unbounded)

    as COD_CONTATTO_LAST,

    ROW_NUMBER() OVER (Partition of COD_CONTATTO

    order of COD_PRIORITY asc, desc FT_DAT_OPEN_CNT

    rows between unbounded preceding and following unbounded)

    as rnum

    of WT_STR_ESG_CONTATTO

    )

    where rnum = 1

    /

    I prefer to use rownumber in this case, so I always have a rnum = 1...

    Usually, you must use the same partition/command by as your other folders (it is usually a good idea... maybe not, depending on your needs, however)

  • Which analytical function to use?


    Hi gurus,

    DB - Oracle 11 g 2

    I followed the examples of data in the table test_a.

    col1 col2 col3

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

    x                 y                   y

    p                 q                  y

    a                b                   y

    p                q                   y

    t                 r                    y

    p                q                   y

    The col3 column is always 'y '. But here's the data p, q, there is repeated 3 times (duplicate) and if this is the case I want to update only the first recordings like "n" col3 it is to say p, q, n. rest will be as it is.

    I am able to get the row_number() for it but not able to do this.

    Select col1, clo2, clo3 row_number() over (partition by col2) arrested by col1 as test_a r_num

    Would it be possible directly by any analytic function?

    Thank you

    SID

    COL4 is logical...

    Something like that?

    with x as)

    Select col1, col2 ' x' 'y', 'y' col3 col4 1 Union double all the

    Select 'p' col1, col2 'q', 'y' col3 col4 2 Union double all the

    Select 'a' col1, col2 'b', 'y' col3 col4 3 of all the double union

    Select 'p' col1, col2 'q', 'y' col3 col4 4 Union double all the

    Select 't' col1, col2 'r', 'y' col3, col4 5 Union double all the

    Select 'p' col1, col2 'q', 'y' col3 col4 6 double

    )

    ---

    Select * from)

    Select x.*,

    ROW_NUMBER() on rn1 (score of col1, col2, col3 col4 sort),

    ROW_NUMBER() on rn2 (partition by col1, col2, col3 col4 desc sorting)

    x

    )

    where rn1 = 1 and rn2 <> 1;

    Understand the logic and simply change SELECT a query to UPDATE...

  • Nth salary using the analytic function

    I use under function to calculate second highest with empno and deptno salary.

    Is it possible to get the same result with another query without using Assembly only analytical functions condition.using and windows function is possible to get the desired output?

    SELECT e.empno,

    e.DEPTNO,

    tmp. SAL as second_higher_salary

    FROM emp e,.

    (SELECT Empno,

    DEPTNO,

    SAL,

    DENSE_RANK() (PARTITION BY deptno ORDER of sal) AS rnk

    WCP

    ) tmp

    WHERE tmp.deptno = e.deptno

    and tmp.rnk = 2

    EMPNO DEPTNO SAL

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

    7934 10 2450

    7782 10 2450

    7839 10 2450

    7876 20 1100

    7369 20 1100

    7902 20 1100

    7788 20 1100

    7566 20 1100

    7900 30 1250

    7844 30 1250

    7654 30 1250

    7521 30 1250

    7499 30 1250

    7698 30 1250

    7900 30 1250

    7844 30 1250

    7654 30 1250

    7521 30 1250

    7499 30 1250

    7698 30 1250

    Here's my solution:

    Select empno,

    DEPTNO,

    FIRST_VALUE (sal) (PARTITION BY deptno ORDER by sal desc)

    de)

    SELECT EmpNo,

    DEPTNO,

    Decode (DENSE_RANK () OVER (PARTITION BY deptno order by sal desc), 1,-sal, sal) sal

    WCP

    )

    /

    EMPNO DEPTNO FIRST_VALUE (SAL) OVER (PARTITIONBYDEPTNOORDERBYSALDESC)

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

      7782 10 2450
      7934 10 2450
      7839 10 2450
      7566 20 2975
      7876 20 2975
      7369 20 2975
      7788 20 2975
      7902 20 2975
      7499 30 1600
      7844 30 1600
      7654 30 1600
      7521 30 1600
      7900 30 1600
      7698 30 1600
  • Analytical function?

    Hello

    I have two tables b rates and transactions (b).

    For each b.FS, I want to know new amount (b.amt time a.rate to the corresponding line of FS b and if a.na is valid based on the flag of the exclusion and the interval defined in the table's).

    It is much easier to explain with an example.

    So here we go...

    Exclude_flag = E (exclude): for b.fs = 433638, b.na = 80000. I have 2 lines in the table for this fs.  Both have E exclude_flag (exclude).  I want to go on all the lines in this FS in the table in a query and I return only one row in the result, if and only if b.na falls out of scope of a.na_min_value and a.na_max_values.  In this example, it falls outside the range excluded for both lines (first two lines of the table a).

    Similarly, exclude_flag = I (Include). for b.fs = 432828, b.na = 17200. I have 2 lines in the table for this fs.  Both have an exclude_flag of I (include).  I want to go on all the lines in this FS in the table in a query and I return only one row in the result, if and only if b.na is between a.na_min_value and a.na_max_values.  In this example, it falls in the range of both the range include for the two lines (line 6 and 7 of the table a).

    The following query gives me two lines for each b.fs.  It is possible to get what I'm looking for simply using sql (possibly write the analytical function?) or I have to write the pl/sql routine for this?

    WITH rates_table

    Did YOU (select ' E' include_exclude_flag, "81000 ' na_min_value, na_max_value '81999', '433638' FS, 0.8 of double rate

    UNION

    Select 'E' include_exclude_flag, na_min_value '84000', na_max_value '84999', '433638' FS, 0.8 of double rate

    UNION

    Select 'I' include_exclude_flag, na_min_value '12000', na_max_value '12999', '432828' FS, rate 0.25 double

    UNION

    Select 'I' include_exclude_flag, na_min_value '13000', na_max_value '13999', '432828' FS, rate 0.25 double

    UNION

    Select 'I' include_exclude_flag, na_min_value '15000', na_max_value '15000', '432828' FS, rate 0.25 double

    UNION

    Select 'I' include_exclude_flag, na_min_value '16100', na_max_value '18000', '432828' FS, rate 0.25 double

    UNION

    Select 'I' include_exclude_flag, '17100' na_min_value, na_max_value '18000', '432828' FS, rate 0.25 double

    UNION

    Select 'I' include_exclude_flag, na_min_value '02440', na_max_value '02470', '016532' FS, 0.35 rate double

    UNION

    Select 'E' include_exclude_flag, na_min_value ' 21000 ', '21000' na_max_value, ' 200020' FS, 0.35 double rate).

    transaction_table AS

    (select '433638' FS '80000' NA, 300 double amt)

    Union

    Select '432828' FS '17200' NA, amt 500 double

    )

    Select * from rates_table a, transaction_table b

    where 1 = 1

    and ((b.na PAS entre a.na_min_value et a.na_max_value et a.include_exclude_flag = «E») GOLD ())

    b.na between a.na_min_value and a.na_max_value and a.include_exclude_flag = 'I'))

    and b.fs = a.fs

    ;

    Any help is greatly appreciated.  I use oracle 11i

    @OP,

    For this kind of problems, we get the number of rows that satisfy the required conditions or who do not meet the required conditions. And then eliminate the line that should be eliminated.

    As below, I calculate four counts (number of join lines)

    EOBCNT - excluded and Out of Bound

    EIBCNT - excluded and in the limit

    IOBCNT - included and Out of Bound

    IIBCNT - included and within the limits

    Once those are calculated, simply return the lines that have EIBCNT and IOBCNT are zero.

    For Ex:

    > WITH

    rates_table

    AS LONG AS)

    Select 'E' include_exclude_flag, na_min_value '79999', na_max_value '79999', '433638' FS, 0.8 double UNION rates

    -Select 'E' include_exclude_flag, na_min_value ' 79999', na_max_value '80000', '433638' FS, 0.8 double UNION rate - TEST - THE

    -If you uncomment the last line and then 433638 will not be returned

    Select 'E' include_exclude_flag, "81000 ' na_min_value, na_max_value '81999', '433638' FS, 0.8 double UNION rates

    Select 'E' include_exclude_flag, na_min_value '84000', na_max_value '84999', '433638' FS, 0.8 double UNION rates

    Select 'I' include_exclude_flag, na_min_value '12000', na_max_value '12999', '432828' FS, 0.25 rate double UNION

    Select 'I' include_exclude_flag, na_min_value '13000', na_max_value '13999', '432828' FS, 0.25 rate double UNION

    Select 'I' include_exclude_flag, na_min_value '15000', na_max_value '15000', '432828' FS, 0.25 rate double UNION

    Select 'I' include_exclude_flag, na_min_value '16100', na_max_value '18000', '432828' FS, 0.25 rate double UNION

    Select 'I' include_exclude_flag, '17100' na_min_value, na_max_value '18000', '432828' FS, 0.25 rate double UNION

    Select 'I' include_exclude_flag, na_min_value '02440', na_max_value '02470', '016532' FS, 0.35 rate double UNION

    Select 'E' include_exclude_flag, na_min_value ' 21000 ', '21000' na_max_value, ' 200020' FS, 0.35 double rate).

    transaction_table AS

    (select '433638' FS '80000' NA, amt 300 Union double

    Select '432828' FS '17200' NA, amt 500 double

    )

    getcnts as)

    SELECT a.*

    b.na, b.amt

    , sum (case when (b.na NOT BETWEEN a.na_min_value)

    AND a.na_max_value

    AND a.include_exclude_flag = 'E '.

    end) then 1 else 0) on (a.fs partition) Eobcnt

    , sum (case when (b.na NOT BETWEEN a.na_min_value)

    AND a.na_max_value

    AND a.include_exclude_flag = 'I '.

    end) then 1 else 0) on (a.fs partition) Iobcnt

    , sum (case when (b.na BETWEEN a.na_min_value)

    AND a.na_max_value

    AND a.include_exclude_flag = 'E '.

    end) then 1 else 0) on (a.fs partition) Eibcnt

    , sum (case when (b.na BETWEEN a.na_min_value)

    AND a.na_max_value

    AND a.include_exclude_flag = 'I '.

    end) then 1 else 0) on (a.fs partition) Iibcnt

    OF rates_table one

    transaction_table b

    WHERE b.fs = a.fs

    )

    getrows as)

    Select x.*, row_number() on

    (partition by order of fs with null desc) getcnts rn x

    where IOBCNT = 0 and eibcnt = 0 - remove lines that are not needed (IF and ONLY if)

    )

    Select * from getrows

    where rn = 1 - to limit a SINGLE row (arbitrarily)

    INCLUDE_EXCLUDE_FLAG NA_MIN_VALUE NA_MAX_VALUE FS RATE NA AMT EOBCNT IOBCNT EIBCNT IIBCNT RN

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

    433638 84999 84000.8 E 80000 300 3 0 0 0 1

    I hope this helps.

  • Order of evaluation of analytic function

    Hello

    have question quite like this:

    with

    -This query selects a 'representative' acct_id by Group (about 300 lines in total)

    acct_repres as

    (

    Select distinct acct_id, origin_id, acct_parm_id of

    (

    Select a.*

    source_id

    , dense_rank() over (partition by order source_id by nulls first, acct_id acct_nbr origin_id) as odr

    account a join account_parm on (a.parm_id = ap.acct_parm_id) ap

    )

    where odr = 1

    )

    Select col1

    col2

    , (select accct_id from ar acct_repres where ar.acct_parm_id = t2.acct_parm_id) col3

    , col4 (select count (1) of acct_repres)

    of une_table t1

    Join other_table t2 on (...)

    And here it is. "Acct_repres" subquery returns more than 300 lines when it is run separately. But when it is used in CTE sometimes (depending on the execution plan) she seems to have that one line - the value in the column col4 is '1 ',.

    While the value of col3 is NULL for most of the cases.

    It looks like the the dense_rank function and the State 'where odr = 1' are evaluated at the end.

    When I use the hint to MATERIALIZE the result was the same.

    But when I put the result of account_repres in the dedicated table and use this table instead of CTE output is correct.

    What is a bug? Or I do something wrong?

    PS: my version of db is 11 GR 1 material (11.1.0.7).

    some unorganized comments:

    -analytical functions are evaluated towards the end of the execution ("' the last set of operations performed in a query with the exception of the final ORDER BY clause"- http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions004.htm")

    -but still the result of a SQL query must be deterministic, so I think that your results are not an expected behavior

    -the CBO has some problems with common table expressions (http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/) if they are of great assistance in the structuring of complex queries. In these cases, you can avoid problems by using inline views

    -Your query uses the common table expressions in scalar subqueries and scalar subqueries are also likely to confuse the CBO. In addition, they are executed once for each row in your result set (or at least for each different correlation value) and can have a negative impact on the performance of the queries in many cases. Often, they can be replaced by outer joins.

    -you say that the suspicion of materialization brings you an erroneous result: the indicator object (online) gives you the correct results?

    Concerning

    Martin Preiss

  • Is there a shorter way (better) with analytical functions?

    Here's a little test scenario:
    create table t 
    ( id   number,
      pos  number,
      typ  number,
      m    number);
      
    insert into t values (1,1,1,100);
    insert into t values (1,2,1,100);
    insert into t values (1,3,2, 50);
    insert into t values (2,1,3, 30);
    insert into t values (2,2,4, 70);
    insert into t values (3,1,1,100);
    insert into t values (3,2,2, 50);
    insert into t values (4,1,3, 30);
    insert into t values (4,2,5, 80);
    insert into t values (4,3,3, 30);
    insert into t values (5,1,3, 30);
    insert into t values (5,2,6, 30);
    insert into t values (6,1,2, 50);
    insert into t values (6,2,7, 50);
    insert into t values (6,3,2, 50);
    insert into t values (7,1,4, 70);
    insert into t values (7,2,4, 70);
    insert into t values (7,3,4, 70);
    For each id, I want to add all the values of m only when they have a different type. It would be a long journey:
    with t1 as
      (select 
         id, 
         typ, 
         min(m) m1 
       from t
       group by id, typ)
    select
      id,
      sum(m1) f
    from t1
    group by id
    order by 1;
    
            ID          F
    ---------- ----------
             1        150 
             2        100 
             3        150 
             4        110 
             5         60 
             6        100 
             7         70 
    but I wonder, is it possible to get this result with a single statement select using analytic functions, something like
    select 
      id, 
      sum(m) over (partition by distinct typ) F    -- this does not work. It's only an idea how it might look like
    from t
    group by id;

    This is firstly a collection with the id, type with calculation of the min for each id, type the combination.
    By subsequently for each id of the sum of the minutes (for each combination of id, type for this particular id) is summarized.

    select distinct
     id, sum(min(m)) over (partition by id)
    from data
    group by id, typ
    order by id
    

    Published by: chris227 on 15.03.2013 07:39

  • Helps the analytic function

    Here is an example of the table data:
    ID    NAME             Start                  
    1     SARA             01-JAN-2006     
    2     SARA             03-FEB-2006     
    3     LAMBDA             21-MAR-2006     
    4     SARA             13-APR-2006     
    5     LAMBDA             01-JAN-2007     
    6     LAMBDA             01-SEP-2007     
    I would get this:
    Name        Start               Stop
    SARA        01-JAN-2006    20-MAR-2006
    LAMBDA      21-MAR-2006     12-APR-2006
    SARA        13-APR-2006     31-DEC-2006
    LAMBDA      01-JAN-2007      <null>
    I tried using partition and run the function but partition name combines all the lines of Sara and Lambda lines into a single group/partition that is not I am trying to get.
    Is there an analytic function or other means to achieve to combine date ranges only when the same person appeared conescutively?
    Thank you.

    This can be easily achieved using tabibitosan:

    First of all, you need to identify 'groups', that each name in the list belongs

    with sample_data as (select 1 id, 'SARA' name, to_date('01/01/2006', 'dd/mm/yyyy') start_date from dual union all
                         select 2 id, 'SARA' name, to_date('03/02/2006', 'dd/mm/yyyy') start_date from dual union all
                         select 3 id, 'LAMBDA' name, to_date('21/03/2006', 'dd/mm/yyyy') start_date from dual union all
                         select 4 id, 'SARA' name, to_date('13/04/2006', 'dd/mm/yyyy') start_date from dual union all
                         select 5 id, 'LAMBDA' name, to_date('01/01/2007', 'dd/mm/yyyy') start_date from dual union all
                         select 6 id, 'LAMBDA' name, to_date('01/09/2007', 'dd/mm/yyyy') start_date from dual)
    select id,
           name,
           start_date,
           lead(start_date, 1, to_date('31/12/9999', 'dd/mm/yyyy')) over (order by start_date) next_start_date,
           row_number() over (order by start_date)
             - row_number() over (partition by name order by start_date) grp
    from   sample_data;
    
            ID NAME   START_DATE NEXT_START_DATE        GRP
    ---------- ------ ---------- --------------- ----------
             1 SARA   01/01/2006 03/02/2006               0
             2 SARA   03/02/2006 21/03/2006               0
             3 LAMBDA 21/03/2006 13/04/2006               2
             4 SARA   13/04/2006 01/01/2007               1
             5 LAMBDA 01/01/2007 01/09/2007               3
             6 LAMBDA 01/09/2007 31/12/9999               3
    

    You can see the group number is generated by comparing the rownumber overall of all lines (in order) with the rownumber of the rowset by name (in the same order) - when there is a gap because another name appears between the two, the group number changes.

    Once you have identified the number of group for each set of rows, it is easy to find the min / max values in this group:

    
    with sample_data as (select 1 id, 'SARA' name, to_date('01/01/2006', 'dd/mm/yyyy') start_date from dual union all
                         select 2 id, 'SARA' name, to_date('03/02/2006', 'dd/mm/yyyy') start_date from dual union all
                         select 3 id, 'LAMBDA' name, to_date('21/03/2006', 'dd/mm/yyyy') start_date from dual union all
                         select 4 id, 'SARA' name, to_date('13/04/2006', 'dd/mm/yyyy') start_date from dual union all
                         select 5 id, 'LAMBDA' name, to_date('01/01/2007', 'dd/mm/yyyy') start_date from dual union all
                         select 6 id, 'LAMBDA' name, to_date('01/09/2007', 'dd/mm/yyyy') start_date from dual),
         tabibitosan as (select id,
                                name,
                                start_date,
                                lead(start_date, 1, to_date('31/12/9999', 'dd/mm/yyyy')) over (order by start_date) next_start_date,
                                row_number() over (order by start_date)
                                  - row_number() over (partition by name order by start_date) grp
                         from   sample_data)
    select name,
           min(start_date) start_date,
           max(next_start_date) stop_date
    from   tabibitosan
    group by name, grp
    order by start_date;
    
    NAME   START_DATE STOP_DATE
    ------ ---------- ----------
    SARA   01/01/2006 21/03/2006
    LAMBDA 21/03/2006 13/04/2006
    SARA   13/04/2006 01/01/2007
    LAMBDA 01/01/2007 31/12/9999
    

    If you want the date to appear as null max, you will need to use a cast or decode to change it - I'll leave that as an exercise for you to do! I'll also let you to find how to get the day before for the stop_date.

  • application of analytic function

    SELECT C, CAL Table;

    THE OUTPUT IS:
    C CAL
    C1 701
    C1 702
    C1 703
    C2 701
    C2 702
    C3 701
    C3 702
    C3 703

    I want using the analytical function and
    get outside like below

    C CAL
    C1 703
    C2 702
    C3 703

    Please guide me how I can get

    Thank you

    Hello

    with data as (
    select 'C1' C, 701 CAL from dual union all
    select 'C1', 702 from dual union all
    select 'C1', 703 from dual union all
    select 'C2', 701 from dual union all
    select 'C2', 702 from dual union all
    select 'C3', 701 from dual union all
    select 'C3', 702 from dual union all
    select 'C3', 703 from dual
    )
    
    select
     c
    ,max(cal)
    from data
    group by
     c
    
    C;MAX(CAL)
    C1;703
    C2;702
    C3;703
    
    You can do this with analytics e.g.
    
    select
     c
    ,max(cal) keep (dense_rank first order by c) over (partition by c ) cal
    from dat
    
    C;CAL
    C1;703
    C1;703
    C1;703
    C2;702
    C2;702
    C3;703
    C3;703
    C3;703
    
    but then you will always do a distinct finally
    
    select distinct
     c
    ,max(cal) keep (dense_rank first order by c) over (partition by c ) cal
    from data
    
    C;CAL
    C3;703
    C2;702
    C1;703
    
    Therefore, at last, you will prefer the group by anyway :-)
    

    Concerning

  • the date of consolidation extends using analytic functions

    I am trying to establish how long a person was in a situation the data looks like this
    person Locator recorded_date
    --------------------------------------------------------
    01/01/2012 10:10 LOC_A PERSON_X
    03/01/2012 PERSON_X LOC_A 15:10
    04/01/2012 PERSON_X LOC_B 02:00
    05/01/2012 PERSON_X LOC_B 11:10
    06/01/2012 PERSON_X LOC_A 03:10

    What I want in the output. I want to divide it into 3 bays. What do I get with min and rank is a grouping of the last loc_a with the first that goes on the average time they were in a different location.
    Start anyone to date date stop
    -----------------------------------------------------------------------------------
    01/01/2012 10:10 01/04/2012 PERSON_X LOC_A 02:00
    04/01/2012 02:00 06/01/2012 PERSON_X LOC_B 03:10
    06/01/2012 PERSON_X LOC_A 03:10

    Hello

    DanU says:
    Thanks Frank! This was extremely helpful. I probably get the final stages. The only piece I am missing is having the end defined by the following date recorded date. So I might try your query with the lead function.

    Sorry, I don't have the sense of end_date.
    You're right; all you need is the analytical function of LEAD to get:

    WITH     got_grp          AS
    (
         SELECT     recorded_date, cqm_category, pat_acct_num
         ,     ROW_NUMBER () OVER ( PARTITION BY  pat_acct_num
                                   ORDER BY          recorded_date
                           )
               -     ROW_NUMBER () OVER ( PARTITION BY  pat_acct_num
                                         ,                    cqm_category
                                   ORDER BY          recorded_date
                           )         AS grp
         FROM    export_table
    )
    SELECT       MIN (recorded_date)               AS start_date
    ,       LEAD (MIN (recorded_date)) OVER ( PARTITION BY  pat_acct_num
                                                 ORDER BY         MIN (recorded_date)
                               )     AS stop_date
    ,       cqm_category
    ,       pat_acct_num
    FROM       got_grp
    GROUP BY  pat_acct_num, cqm_category, grp
    ORDER BY  pat_acct_num, start_date
    ;
    

    It's almost the same query as what I posted before.
    Apart from substituting your new table and column names, the only change I made was how stop_date is defined in the main query.

  • Ask in analytic function

    Hello
    I use under request

    Select * from
    (
    SELECT FLAG, S_DATE, ROW_NUMBER () OVER (PARTITION OF)
    order by S_DATE, FLAG flag) d
    Table_name FROM
    ORDER BY S_DATE
    );

    below the output which gives

    Flag | S_DATE | D
    Y     | 27/02/2012 05:33 |     1
    Y     | 27/02/2012 05:34 |     2
    Y     | 27/02/2012 05:34 |     3
    N     | 27/02/2012 05:34 |     1
    N     | 27/02/2012 05:34 |     2
    N     | 27/02/2012 05:34 |     3
    N     | 27/02/2012 05:35 |     4
    N     | 27/02/2012 05:35 |     5
    Y     |  27/02/2012 05:36 |     4
    Y     |  27/02/2012 05:36 |     5
    Y     |  27/02/2012 05:36 |     6


    But I want the output to be below order is changed in the last 3 rows

    Flag | S_DATE | D

    Y     | 27/02/2012 05:33 |     1
    Y     | 27/02/2012 05:34 |     2
    Y     | 27/02/2012 05:34 |     3
    N     | 27/02/2012 05:34 |     1
    N     | 27/02/2012 05:34 |     2
    N     | 27/02/2012 05:34 |     3
    N     | 27/02/2012 05:35 |     4
    N     | 27/02/2012 05:35 |     5
    Y     |  27/02/2012 05:36 |     1
    Y     |  27/02/2012 05:36 |     2
    Y     |  27/02/2012 05:36 |     3

    I used the analytical function.

    Published by: user8858890 on February 27, 2012 02:00

    Hello

    user8858890 wrote:
    ... But I want the output to be below order is changed in the last 3 rows

    Flag | S_DATE | D

    Y     | 27/02/2012 05:33 |     1
    Y     | 27/02/2012 05:34 |     2
    Y     | 27/02/2012 05:34 |     3
    N     | 27/02/2012 05:34 |     1
    N     | 27/02/2012 05:34 |     2
    N     | 27/02/2012 05:34 |     3
    N     | 27/02/2012 05:35 |     4
    N     | 27/02/2012 05:35 |     5
    Y     |  27/02/2012 05:36 |     1
    Y     |  27/02/2012 05:36 |     2
    Y     |  27/02/2012 05:36 |     3

    Why do you want the last 3 lines (who have the flag = 'Y') to be numbered 1, 2, 3, when the first 3 lines (who also have the flag = "Y") already have the numbers 1, 2 and 3? Do you want a separate whenevever #1 there is a group of consecutive lines (when ordered by s_date) who have the same flag? If so, you need to identify the groups, like this:

    WITH     got_grp_id     AS
    (
         SELECT     flag
         ,     s_date
         ,     ROWID               AS r_id
         ,     ROW_NUMBER () OVER ( ORDER BY      s_date
                                   ,                  ROWID
                           )
               - ROW_NUMBER () OVER ( PARTITION BY  flag
                                         ORDER BY          s_date
                             ,               ROWID
                           )    AS grp_id
         FROM    table_name
    )
    SELECT       flag
    ,       s_date
    ,       ROW_NUMBER () OVER ( PARTITION BY  flag
                                 ,          grp_id
                          ORDER BY          s_date
                          ,               r_id
                        )      AS d
    FROM      got_grp_id
    ORDER BY  s_date
    ,            grp_id
    ,       d
    ;
    

    This assumes that each line can be unique idendified, so that the order is unambiguous. In your sample data, there is completely identical lines, so I used the ROWID to uniquely identify the lines. Using ROWID suppose table_name is a real table, not just a game of results.

    I hope that answers your question.
    If not, post a small example of data (CREATE TABLE and only relevant columns, INSERT statements) for all of the tables involved and the results desired from these data.
    Explain, using specific examples, how you get these results from these data.
    Always tell what version of Oracle you are using.

  • May result by analytic function that follows

    Hi all

    I am currently using oracle 10g.

    create table
    CREATE TABLE fortest
    (  PROD             VARCHAR2(40 BYTE),
      prodvalues     number);
    INSERT statement
    insert into fortest values ('dental',10)
       insert into fortest values ('dental',4)
        insert into fortest values ('dental',13)
         insert into fortest values ('dental',3)
          insert into fortest values ('vision',2)
           insert into fortest values ('vision',11)
           insert into fortest values ('vision',33) 
            insert into fortest values ('vision',7)
    I need the output as follows
    prod        prodvalues <5         prodvalues >=5 and less than 10               prodvalues >=10
    dental         2                                     0                                      2
    vision         1                                     1                                      2
    first column should give me separate prod, prodvalues5 column: should give me the number of similar prod with prodvalues less than 5, same thirdcolumn should have County of similar prod with prodvalues > = 5 and prodvalue < 10 and so on.

    Please, not the names of columns of the output tables are just for reference, and I will not use them.


    Thanks in advance.

    Hi Bob,

    You don't have to use analytical functions. Here's a solution that doesn't use analytical functions:

    with temp as (select prod, case
                               when prodvalues <=5 then 1
                               else                    0
                               end  as prod5,
                               case
                               when prodvalues >=5 and prodvalues <10 then 1
                               else                    0
                               end  as prod5_10,
                               case
                               when prodvalues >= 10 then 1
                               else                    0
                               end  as prod10
                               from fortest)
                               select prod,sum(prod5) as prod5 ,  sum(prod5_10) as prod5_10 ,sum(prod10) as prod10
                               from temp
                               group by prod
    
  • get a single result with analytical functions

    SELECT delrazjn. TYPE, delrazjn. DATE, delrazjn. USER, delrazjn. The IID OF the ZKET_DR delraz, ZKET_DR_JN delrazjn
    WHERE delraz. IID = delrazjn. IID
    AND (delrazjn. TYPE = 'UP2' GOLD delrazjn. TYPE = 'An increase in 1') AND delrazjn. IID_N IS NOT NULL

    This is an example of my sql. But there is more than one result of delrazjn. IID. How can I get the first enterd in DB and ignore others, there will only be one result and no more.
    The first result came in, that I can see for delrazjn. DATE.

    I try to do that with analytical functions, but without success.

    You're right, I told you that I can't test the code.

    I hope this works now:

    SELECT delrazjn.TYPE, delrazjn.DATE, delrazjn.USER, delrazjn.IID
    FROM ZKET_DR delraz, ZKET_DR_JN delrazjn
    WHERE delraz.IID = delrazjn.IID
    AND (delrazjn.TYPE = 'UP2' OR delrazjn.TYPE = 'UP1') AND delrazjn.IID_N IS NOT NULL
    and delrazjn.date=(select min(d.date) from ZKET_DR_JN d where d.type=delrazjn.type and d.user=delrazjn.user)
    
  • [8i] can I use an analytical function, or do I need a subquery?

    Hi all...

    This should be a quick. I hope I can solve my problem with an analytic function, but I don't know if it's possible. Can I use a subquery if I have to, but I'd really rather not.

    Here is a very simple version of what I'm trying to do:
    CREATE TABLE     test123
    (     field1          VARCHAR2(10)
    ,     field2          VARCHAR2(10)
    ,     my_date          DATE
    );
    
    INSERT INTO     test123
    VALUES     ('value1', 'a',TO_DATE('12/31/1900','mm/dd/yyyy'));
    INSERT INTO     test123
    VALUES     ('value1', 'b',TO_DATE('01/02/2010','mm/dd/yyyy'));
    INSERT INTO     test123
    VALUES     ('value1', 'c',TO_DATE('01/05/2010','mm/dd/yyyy'));
    
    INSERT INTO     test123
    VALUES     ('value2', 'a',TO_DATE('12/31/1900','mm/dd/yyyy'));
    INSERT INTO     test123
    VALUES     ('value2', 'b',TO_DATE('01/01/2010','mm/dd/yyyy'));
    INSERT INTO     test123
    VALUES     ('value2', 'c',TO_DATE('01/15/2010','mm/dd/yyyy'));
    I want the results:
    FIELD1     FIELD2
    --------------
    value2     a
    value2     b
    value2     c
    value1     a
    value1     b
    value1     c
    I started with the following query:
    SELECT     field1
    ,          field2
    FROM     test123
    ORDER BY     MIN(my_date)     OVER     (
                                                 PARTITION BY     field1
                                                 )                                -- removed DESC here
    ,               field2
    But the problem is the database has a date of 31 December 1900 ' as default / initial for any date field. I don't want these default values taken into account in my calculation of min. I tried to put a WHERE clause in my analytical function [WHERE my_date <>TO_DATE (' 12/31/1900 ',' mm/dd/yyyy')], but I kept getting an error message "missing right parenthesis", so it seems that you can not have a WHERE clause here... or I'm just something wrong?

    Moreover, it is a 8i database...

    Edited by: user11033437 may 20, 2010 17:16: took the 'DESC' criteria out of my order by clause. In my real application, I need DESC, but not the example.

    Hello

    A WHERE clause excludes rows in the results set. Whenever you want you can have a WHERE clause that was more limited (for example, something that would simply exclude MIN calculating values in the ORDER BY clause), then think CASE:

    SELECT       field1
    ,       field2
    FROM       test123
    ORDER BY  MIN ( CASE
                  WHEN  my_date > TO_DATE ( '12/31/1900'
                                 , 'MM/DD/YYYY'
                                 )
                  THEN  my_date
              END
               )     OVER     (PARTITION BY     field1)      DESC
    ,       field2
    ;
    

    This puts the lines for "Value1" first.
    The minimum my_date for "Value1" (after excluding the values of 1900) is later than the minimum for "Value2", so I think that you either made a mistake in the desired output, or you do not want sorted by descending order.

    As always, thanks for the display of the data of the sample and the results so clearly.

Maybe you are looking for

  • White flashing light on my Tower in early 2008

    Hi people, I have a Mac Pro 2008 beginning 2.8 Mavericks 10.9.5 running 2xquald.  Since the update about a month ago my Mac is acting strange.  During the race, fans will ramp up to maximum and keep doing this until I hold the power button to turn of

  • End of 2012 Mac Mini running slow - about to try the following

    Hi all The performance of my Mac Mini is trying to drop off and looking for possible solutions to this, I can in this thread: Mac Mini (end 2012) is a little slow. A few months ago I updated to El Capitan, and am now on 10.11.3.  Since this update, m

  • How to use a 2nd partition to store data?

    The 40 GB HDD on my satellite L10 comes with two 20 GB partitions (C and D drive). I understood (by reading this forum) that it is better to use a partition to store the data. So far, there was no need to use the D drive. But now I need more space. H

  • G50 - 30 - lack of Wifi Realtek Driver for Windows 8.1 on Lenovo G50 - 30

    Hi guys, im going to install windows 8.1 on my lenovo g50-30, but thers no Realtek wifi driver for download, only Intel, anyonee has an idea where to find? Mod edit: System model added to the front of the subject line to improve visibility / clarity.

  • Windows Media Player does not recognize the device (iphone)

    I'm trying to download music from Windows Media Player on my iphone. I can get the files in the synchronization section but the Media Player does not recognize my device or seem to have a way to connect. Can anyone help?