Analytical function - COUNT issue

Hi all

DB Oracle 11 g running on 64-bit Linux x 86 platform...

I'm curious to know why the underside of two sets of queries produce different results.

Q 1

------

WITH TEMP AS

(

SELECT 'A' VAL BY DOUBLE UNION ALL 5

SELECT 'A' VAL BY 7 OF DOUBLE UNION ALL

SELECT 'FIVE' VAL BY 17 DOUBLE UNION ALL

SELECT 'FOUR' VAL BY 0 FROM DUAL UNION ALL

SELECT 'THREE' VAL BY 78 OF DOUBLE UNION ALL

SELECT 'THREE' VAL BY 34 FROM DUAL UNION ALL

SELECT 'THREE' VAL, PAR 4 FROM DUAL UNION ALL

SELECT 'TWO' VAL BY 6 IN DOUBLE UNION ALL

SELECT "TWO" VAL, 12 BY DOUBLE

)

SELECT SUM (BY) OVER SEPARATE (PARTITION OF VAL), VAL NTC TEMP.

Q2

----

WITH TEMP AS

(

SELECT 'A' VAL BY DOUBLE UNION ALL 5

SELECT 'A' VAL BY 7 OF DOUBLE UNION ALL

SELECT 'FIVE' VAL BY 17 DOUBLE UNION ALL

SELECT 'FOUR' VAL BY 0 FROM DUAL UNION ALL

SELECT 'THREE' VAL BY 78 OF DOUBLE UNION ALL

SELECT 'THREE' VAL BY 34 FROM DUAL UNION ALL

SELECT 'THREE' VAL, PAR 4 FROM DUAL UNION ALL

SELECT 'TWO' VAL BY 6 IN DOUBLE UNION ALL

SELECT "TWO" VAL, 12 BY DOUBLE

)

SELECT SUM (BY) SEPARATE DURING THE CNT (PARTITION BY ORDER OF VAL BY IRON), VAL TEMP;

The only difference between the 2 queries is that Q2 has the additional "ORDER BY".

For the 2nd quarter, I am assuming that the partitions are classified by the RAILWAY and the SUM is applied on the partition. Obviously, the results prove that my assumption is wrong.

So, Q2 is as good as select * TEMP;

Hello

You're right about 'ORDER BY per'; This means that the SUM will be the lowest nominal value up to and including the current line.

I think you're ignoring "PARTITION BY val", which means that each distinct value of val will be a world in itself, not affected by all the lines with a different value of val.  Val is different on each row, it means that the indicated SUM will always be the SUM of just 1 point, so SUM (RAP) will be the same only by.

Try it without the PARTITION BY clause.

Tags: Database

Similar Questions

  • Using the analytic function

    Oracle 11g Release 2

    I'm assuming that the best solution is the use of analytical functions.

    create table test3
    ( part_type_id  varchar2(50)
    ,group_id      number
    ,part_desc_id  number
    ,part_cmt      varchar2(50)
    )
    /
    
    insert into test3 values( 'ABC123',1,10,'comment1');
    insert into test3 values( 'ABC123',1,10,'comment2');
    insert into test3 values( 'ABC123',2,15,'comment1');
    insert into test3 values( 'ABC123',2,15,'comment2');
    insert into test3 values( 'EFG123',25,75,'comment3');
    insert into test3 values( 'EFG123',25,75,'comment4');
    insert into test3 values( 'EFG123',25,75,'comment5');
    insert into test3 values( 'XYZ123',1,10,'comment6');
    insert into test3 values( 'XYZ123',2,15,'comment7');
    commit;
    
    select * from test3;
    
    PART_TYPE_ID           GROUP_ID PART_DESC_ID PART_CMT
    -------------------- ---------- ------------ --------------------
    ABC123                        1           10 comment1
    ABC123                        1           10 comment2
    ABC123                        2           15 comment1
    ABC123                        2           15 comment2
    EDG123                        25          75 comment3
    EDG123                        25          75 comment4
    EDG123                        25          75 comment5
    XYZ123                        1           10 comment6
    XYZ123                        2           15 comment7
    
    9 rows selected.
    
    Desired output:
    
    PART_TYPE_ID           GROUP_ID PART_DESC_ID PART_CMT
    -------------------- ---------- ------------ --------------------
    ABC123                        1           10 comment1 
    ABC123                        2           15 comment1
    XYZ123                        1           10 comment1
    XYZ123                        2           15 comment2
    
    RULE: where one part_type_id has multiple (2 or more distinct combinations) of group_id/part_desc_id
    
    NOTE: There are about 12 columns in the table, for brevity I only included 4.
    
    
    
    

    Post edited by: orclrunner was updated desired output and rule

    Hello

    Here's one way:

    WITH got_d_count AS

    (

    SELECT part_type_id, group_id, part_desc_id

    MIN (part_cmt) AS min_part_cmt

    COUNT AS d_count (*) OVER (PARTITION BY part_type_id)

    OF test3

    GROUP BY part_type_id, group_id, part_desc_id

    )

    SELECT DISTINCT

    group_id, part_desc_id, part_type_id, min_part_cmt

    OF got_d_count

    WHERE d_count > 1

    ;

    Output:

    GROUP_ID PART_DESC_ID MIN_PART_CMT PART_TYPE_ID

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

    ABC123 1 10 comment1

    ABC123 2 15 comment1

    XYZ123 1 10 comment6

    XYZ123 2 15 comment7

    Analytical functions, such as the COUNTY and MIN, many global versions, in addition, it can give the same results.  Use the analytical versions when each row of output corresponds to exactly 1 row of input and the aggregate and GROUP BY version when each line of output corresponds to a group of lines 1 or more input.  In this issue, each line of output appears to be a group of input lines having the same group_id, part_type_id, and part_desc_id (I'm guessing just, this only has never stated), so I used GROUP BY to get 1 row of output for every input lines.

  • 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

  • SQL using the analytic function


    Hi all

    I want a help in the creation of my SQL query to retrieve the data described below:

    I have a test of sample table containing data as below:

    State ID Desc

    MICHAEL 1 T1

    ACTIVE 2 T2

    T3 3 SUCCESS

    DISABLE THE T4 4

    The thing I want to do is to select all the lines with an ACTIVE status in the table but is there is no ACTIVE status, my request will give me the last line with MICHAEL status.

    I can do this in a single request by using the analytical function for example, if yes can yiu help me on the request of unpacking.

    Kind regards

    Raluce

    Something like that?

    I had to fix it.

    with testdata until)
    Select 1 id, "T1" dsc "DISABLED" status of Union double all the
    Select 2 id, 'T2' dsc, the status "ACTIVE" of all the double union
    Select id 3, "T3" dsc, the status of 'SUCCESS' of all the double union
    Select 4 id, "T4" dsc "DISABLED" status of double
    )

    Select
    ID
    dsc
    status
    of testdata
    where
    status =
    -case when (select count (*) in testdata where status = 'ACTIVE') > 0
    then 'ACTIVE '.
    Another 'DISABLED '.
    end
    and)
    ID in (select id from testdata where status = ' ACTIVE')
    or
    ID = (select max (id) in testdata when status = 'DISABLED')
    )

    STATE ID DSC

    '2' 'T2' 'ACTIVE '.

    Maybe it's more efficient

    Select
    ID
    dsc
    status
    of testdata
    where
    status =
    -case when (select count (*) in testdata where status = 'ACTIVE') > 0
    then 'ACTIVE '.
    Another 'DISABLED '.
    end
    and
    ID =)
    -case when (select count (*) in testdata where status = 'ACTIVE') > 0
    then id
    on the other
    (select max (id) in testdata when status = 'DISABLED')
    end
    )

    Post edited by: correction of chris227

    Post edited by: chris227
    extended

  • Analytical functions, model indexes and multiple dimensions.

    I don't understand the notion of analytic functions (windowing clause) in the regulation of a model clause. I discovered an ordinary table as one-dimensional, and I can understand the concept of window, just like a line on a segment line. However with the models, there are several dimensions, so I guess that the window to become a kind of cube, instead of a line segment. But I'm not.

    For example, I have a matrix sparse 2D, with 5 values non-zero:
    select * from field
      where f is not null
    
    X     Y     F
    -----------------
    5     8     X
    6     6     X
    6     8     X
    7     7     X
    7     8     X
    I guess that the following clause of the model
    with t as(
      select *
        from field
       model
         reference old_field
           on
           (
             select * from field
           )
           dimension by (x, y)
           measures     (f)
         main new_field
           dimension by (x, y)
           measures     (cast(f as varchar2(3)) f)
           rules
           (
             f[x,y] = max(old_field.f) over (order by old_field.y range between 1 preceding and 1 following)
           ))
    select * from t
      where f is not null
    to assign for each cell up among its neighbors vertical 2. Just like
    0 0 0      0 X 0
    0 X 0  ->  X X 0
    X 0 0      X X 0
    But the real result is all NULL values.

    Hello

    with a as
    (
    select
    level L
    from
    dual
    connect by level < 4
    )
    
    select
         X
         ,Y
         ,Z
         ,X*3+Y
    
    from
         a          A1
         ,A     A2
    
    model
         dimension by ( A1.L X, A2.L Y )
         MEASURES (0 Z)
         RULES
         (
         Z[X,Y] = COUNT(Z) OVER (ORDER BY X * 3 + Y RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING)
         )
    
    X Y Z X*3+Y
    - - - -----
    1 1 2     4
    1 2 3     5
    1 3 3     6
    2 1 3     7
    2 2 3     8
    2 3 3     9
    3 1 3    10
    3 2 3    11
    3 3 2    12 
    
     9 rows selected 
    

    for x, y = 1.1, there is no previous rank if it is not counted. current line + line = 2
    for x, y = 1, 2, the previous line + line current + more rank = 3
    for x, y = 1.3 the previous line + line current + more rank = 3
    for x, y = 2, 1, the previous line + line current + more rank = 3
    ...
    for x, y = 3, 2 the previous line + line current + more rank = 3
    for x, y = 3, 3 the stored previous + current line = 2. There is no next line.

    What exectly not understand you?

    Kind regards
    Peter

  • Purpose of the ORDER BY clause in the analytic function Min Max

    I was always using analytical functions like Min Max without ORDER BY clause. But today I used with the ORDER BY clause. The results are very different. I would like to know the purpose of the ORDER BY clause in Min, Max and analogues of analytical functions.

    user10566312 wrote:
    I was always using analytical functions like Min Max without ORDER BY clause. But today I used with the ORDER BY clause. The results are very different. I would like to know the purpose of the ORDER BY clause in Min, Max and analogues of analytical functions.

    It is a good point that many developers are not so aware. As far as I understand it the way it works.

    Some analytical functions do not need an order by or windowing clause (SUM, COUNT, MIN, etc.). If there is no specified window, then the full score is the window.
    As soon as you add a command also add you a windowing clause. This window has the default value of 'rank ofrows between unbounded preceding and current_row. So as soon as you add an order by clause, you get a sliding window.

    Documentation: http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm

    windowing_clause
    ...
    You cannot specify this clause unless you specified the order_by_clause. Window limits defined by the clause RANGE you can not specify only a single expression to the > order_by_clause. Please refer to 'Restrictions on the ORDER BY Clause'.

    example of

    with testdata as (select 10 numval, level lv from dual connect by level < 10)
    select lv, numval, sum(numval) over () sum1, sum(numval) over (order by lv) sum2
    from testdata;
    
    LV NUMVAL SUM1 SUM2
    -- ------ ---- ----
     1     10   90   10
     2     10   90   20
     3     10   90   30
     4     10   90   40
     5     10   90   50
     6     10   90   60
     7     10   90   70
     8     10   90   80
     9     10   90   90 
    

    Published by: Sven w. on 25 Sep 2012 16:57 - default behavior has been corrected. Thanks to Chris

  • problem of analytic function

    Hello

    I have a problem using the analytical function: when I run this query

    SELECT TSIUPSITE, TSIUPCEAN, TSIUPDATE, sum (TSIUPCA) TSIUPCA, TSIUPCTVA, TSIUPP4N, TSIUPPIEC,.
    Sum (TSIUPQTE) TSIUPQTE, sum (TSIUPQTEP) TSIUPQTEP, TSIUPMDIU, TSIUPMDar,
    Sum (TSIUPCRIU) TSIUPCRIU, sum (TSIUPCRAR) TSIUPCRAR, trunc (TSIUPDCRE) TSIUPDCRE, trunc (TSIUPDMAJ) TSIUPDMAJ,
    TSIUPUTIL, TSIUPTRT, TSIUPNERR, TSIUPMESS.
    TSIUPTMVT, TSIUPSMAN, TSIUPMOTIF, sum (TSIUPMHT) TSIUPMHT, 0 vtanfisc.
    TSIUPDATEVERIF, TSIUPNSEQ, TSIUPCINV, count (*) over (partition TSIUPSITE, TSIUPCEAN, TSIUP_TRT) CONTA_ARTICOLO
    OF TST_FLIISR_VTEREMART
    WHERE 1 = 1 - TSIUP_TRT = 1
    AND TSIUPDATE = to_date('27082012','ddmmyyyy')
    and TSIUP_NTRX = 172
    AND TSIUPSITE = 10025
    AND TSIUPCEAN = '8012452018825'
    GROUP OF TSIUPSITE, TSIUPCEAN, TSIUPDATE, TSIUPCTVA, TSIUPP4N, TSIUPPIEC,
    TSIUPMDIU, TSIUPMDar, trunc (TSIUPDCRE), trunc (TSIUPDMAJ), TSIUPUTIL, TSIUPTRT, TSIUPNERR, TSIUPMESS,
    TSIUPTMVT, TSIUPSMAN, TSIUPMOTIF, 0,
    TSIUPDATEVERIF, TSIUPNSEQ, TSIUPCINV
    ORDER OF TSIUPSITE, TSIUPDATE;

    I have the error ORA-00979: not an expression GROUP BY related to the area of TSIUP_TRT, infact, if I run it

    SELECT TSIUPSITE, TSIUPCEAN, TSIUPDATE, sum (TSIUPCA) TSIUPCA, TSIUPCTVA, TSIUPP4N, TSIUPPIEC,.
    Sum (TSIUPQTE) TSIUPQTE, sum (TSIUPQTEP) TSIUPQTEP, TSIUPMDIU, TSIUPMDar,
    Sum (TSIUPCRIU) TSIUPCRIU, sum (TSIUPCRAR) TSIUPCRAR, trunc (TSIUPDCRE) TSIUPDCRE, trunc (TSIUPDMAJ) TSIUPDMAJ,
    TSIUPUTIL, TSIUPTRT, TSIUPNERR, TSIUPMESS.
    TSIUPTMVT, TSIUPSMAN, TSIUPMOTIF, sum (TSIUPMHT) TSIUPMHT, 0 vtanfisc.
    TSIUPDATEVERIF, TSIUPNSEQ, TSIUPCINV, count (*) over (partition TSIUPSITE, TSIUPCEAN) CONTA_ARTICOLO
    OF TST_FLIISR_VTEREMART
    WHERE 1 = 1 - TSIUP_TRT = 1
    AND TSIUPDATE = to_date('27082012','ddmmyyyy')
    and TSIUP_NTRX = 172
    AND TSIUPSITE = 10025
    AND TSIUPCEAN = '8012452018825'
    GROUP OF TSIUPSITE, TSIUPCEAN, TSIUPDATE, TSIUPCTVA, TSIUPP4N, TSIUPPIEC,
    TSIUPMDIU, TSIUPMDar, trunc (TSIUPDCRE), trunc (TSIUPDMAJ), TSIUPUTIL, TSIUPTRT, TSIUPNERR, TSIUPMESS,
    TSIUPTMVT, TSIUPSMAN, TSIUPMOTIF, 0,
    TSIUPDATEVERIF, TSIUPNSEQ, TSIUPCINV
    ORDER OF TSIUPSITE, TSIUPDATE;

    I have no problem. Now the difference between the TSIUPCEAN (or TSIUPSITE) and TSIUP_TRT that TSIUP_TRT is not in the Group By clause, but, to be honest, I don't know why I have this problem using using an analytic function.

    Thanks for help

    Hello

    I think that you are not analytic function correctly.

    Analytical functions will be run for each line. Where as Group BY will run for groups of data.

    See example below for you reference.

    Example 1:
    
    -- Below query displays number of employees for each department. Since we have used analytical function for each row you are getting the number of employees based on the department id.
    
    SQL> SELECT e.department_id,count(*) OVER (PARTITION BY e.department_id) cnt_analytic
      2  FROM employees e
      3  WHERE e.department_id IN (10,20,30);
    
    DEPARTMENT_ID CNT_ANALYTIC
    ------------- ------------
               10            1
               20            2
               20            2
               30            6
               30            6
               30            6
               30            6
               30            6
               30            6
    
    9 rows selected.
    
    Example 2:
    
    -- Since I have used GROUP BY clause I'm getting only single row for each department.
    
    SQL> SELECT e.department_id, count(*) cnt_group
      2  FROM employees e
      3  WHERE e.department_id IN (10,20,30)
      4  GROUP BY e.department_id;
    
    DEPARTMENT_ID  CNT_GROUP
    ------------- ----------
               10          1
               20          2
               30          6
    

    Finally, what I'm trying to explain is - if you use the analytical function with the GROUP BY clause, the query will not give the ful menaing result set.

    See below

    SQL> SELECT e.department_id,count(*) OVER (PARTITION BY e.department_id) cnt_analytic, count(*) cnt_grp
      2  FROM employees e
      3  WHERE e.department_id IN (10,20,30)
      4  GROUP BY e.department_id;
    
    DEPARTMENT_ID CNT_ANALYTIC    CNT_GRP
    ------------- ------------ ----------
               10            1          1
               20            1          2
               30            1          6
    
  • Problem with analytical function for date

    Hi all

    ORCL worm:
    Oracle Database 11 g Enterprise Edition Release 11.2.0.2.0 - 64 bit Production
    PL/SQL Release 11.2.0.2.0 - Production
    "CORE 11.2.0.2.0 Production."
    AMT for Linux: Version 11.2.0.2.0 - Production
    NLSRTL Version 11.2.0.2.0 - Production

    I have a problem with the analtical for the date function. I'm trying to group records based on timestamp, but I'm failing to do.
    Could you please help me find where I'm missing.
    This is the subquery. No issue with this. I'm just posting it for reference. 
    select sum(disclosed_cost_allocation.to_be_paid_amt) amt,
        substr(reference_data.ref_code,4,10) cd,
        to_char(external_order_status.status_updated_tmstp, 'DD-MON-YYYY HH24:MI:SS') tmstp,
        DISCLOSED_CLOSING_COST.DISCLOSED_CLOSING_COST_ID id
      FROM Deal.Fee_Mapping_Definition ,
        Deal.Fee_Index_Definition ,
        Deal.Fee_Closing_Cost_Item,
        Deal.Closing_Cost,
        Deal.Document_Generation_Request,
        deal.PRODUCT_REQUEST,
        deal.External_Order_Request,
        deal.External_Order_Status,
        deal. DISCLOSED_CLOSING_COST,
        deal.DISCLOSED_COST_ALLOCATION,
        deal.reference_data
      WHERE Fee_Mapping_Definition.Fee_Code                    = Fee_Index_Definition.Fee_Code
      AND Fee_Index_Definition.Fee_Index_Definition_Id         = Fee_Closing_Cost_Item.Fee_Index_Definition_Id
      AND Fee_Closing_Cost_Item.Closing_Cost_Id                = Closing_Cost.Closing_Cost_Id
      AND CLOSING_COST.PRODUCT_REQUEST_ID                      = Document_Generation_Request.Product_Request_Id
      AND closing_cost.product_request_id                      = product_request.product_request_id
      AND Product_Request.Deal_Id                              = External_Order_Request.Deal_Id
      AND external_order_request.external_order_request_id     = external_order_status.external_order_request_id
      AND external_order_request.external_order_request_id     = disclosed_closing_cost.external_order_request_id
      AND DISCLOSED_CLOSING_COST. DISCLOSED_CLOSING_COST_ID    = DISCLOSED_COST_ALLOCATION.DISCLOSED_CLOSING_COST_ID
      AND Fee_Index_Definition.Fee_Index_Definition_Id         = Disclosed_Closing_Cost.Fee_Index_Definition_Id
      AND Fee_Mapping_Definition.Document_Line_Series_Ref_Id   = Reference_Data.Reference_Data_Id
      AND Document_Generation_Request.Document_Package_Ref_Id IN (7392 ,2209 )
      AND External_Order_Status.Order_Status_Txt               = ('GenerationCompleted')
      AND Fee_Mapping_Definition.Document_Line_Series_Ref_Id  IN ( 7789, 7788,7596 )
      AND FEE_MAPPING_DEFINITION.DOCUMENT_TYPE_REF_ID          = 1099
      AND Document_Generation_Request.Product_Request_Id      IN
        (SELECT PRODUCT_REQUEST.PRODUCT_REQUEST_id
        FROM Deal.Disclosed_Cost_Allocation,
          Deal.Disclosed_Closing_Cost,
          DEAL.External_Order_Request,
          DEAL.PRODUCT_REQUEST,
          Deal.Scenario
        WHERE Disclosed_Cost_Allocation.Disclosed_Closing_Cost_Id = Disclosed_Closing_Cost.Disclosed_Closing_Cost_Id
        AND Disclosed_Closing_Cost.External_Order_Request_Id      = External_Order_Request.External_Order_Request_Id
        AND External_Order_Request.Deal_Id                        = Product_Request.Deal_Id
        AND product_request.scenario_id                           = scenario.scenario_id
        AND SCENARIO.SCENARIO_STATUS_TYPE_REF_ID                  = 7206
        AND product_request.servicing_loan_acct_num              IS NOT NULL
        AND product_request.servicing_loan_acct_num               = 0017498379
          --AND Disclosed_Cost_Allocation.Disclosed_Cost_Allocation_Id = 5095263
        )
      GROUP BY DISCLOSED_CLOSING_COST.DISCLOSED_CLOSING_COST_ID,
        External_Order_Status.Status_Updated_Tmstp,
        Reference_Data.Ref_Code,
        disclosed_cost_allocation.to_be_paid_amt
      order by 3 desc,
        1 DESC;
    
    Result:
    2000     1304-1399     28-JUL-2012 19:49:47     6880959
    312     1302     28-JUL-2012 19:49:47     6880958
    76     1303     28-JUL-2012 19:49:47     6880957
    2000     1304-1399     28-JUL-2012 18:02:16     6880539
    312     1302     28-JUL-2012 18:02:16     6880538
    76     1303     28-JUL-2012 18:02:16     6880537
    
    
    But, when I try to group the timestamp using analytical function,
    
    
    select amt 
            ,cd 
            ,rank() over(partition by tmstp order by tmstp desc) rn 
    from 
    (select sum(disclosed_cost_allocation.to_be_paid_amt) amt,
        substr(reference_data.ref_code,4,10) cd,
        to_char(external_order_status.status_updated_tmstp, 'DD-MON-YYYY HH24:MI:SS') tmstp,
        DISCLOSED_CLOSING_COST.DISCLOSED_CLOSING_COST_ID id
      FROM Deal.Fee_Mapping_Definition ,
        Deal.Fee_Index_Definition ,
        Deal.Fee_Closing_Cost_Item,
        Deal.Closing_Cost,
        Deal.Document_Generation_Request,
        deal.PRODUCT_REQUEST,
        deal.External_Order_Request,
        deal.External_Order_Status,
        deal. DISCLOSED_CLOSING_COST,
        deal.DISCLOSED_COST_ALLOCATION,
        deal.reference_data
      WHERE Fee_Mapping_Definition.Fee_Code                    = Fee_Index_Definition.Fee_Code
      AND Fee_Index_Definition.Fee_Index_Definition_Id         = Fee_Closing_Cost_Item.Fee_Index_Definition_Id
      AND Fee_Closing_Cost_Item.Closing_Cost_Id                = Closing_Cost.Closing_Cost_Id
      AND CLOSING_COST.PRODUCT_REQUEST_ID                      = Document_Generation_Request.Product_Request_Id
      AND closing_cost.product_request_id                      = product_request.product_request_id
      AND Product_Request.Deal_Id                              = External_Order_Request.Deal_Id
      AND external_order_request.external_order_request_id     = external_order_status.external_order_request_id
      AND external_order_request.external_order_request_id     = disclosed_closing_cost.external_order_request_id
      AND DISCLOSED_CLOSING_COST. DISCLOSED_CLOSING_COST_ID    = DISCLOSED_COST_ALLOCATION.DISCLOSED_CLOSING_COST_ID
      AND Fee_Index_Definition.Fee_Index_Definition_Id         = Disclosed_Closing_Cost.Fee_Index_Definition_Id
      AND Fee_Mapping_Definition.Document_Line_Series_Ref_Id   = Reference_Data.Reference_Data_Id
      AND Document_Generation_Request.Document_Package_Ref_Id IN (7392 ,2209 )
      AND External_Order_Status.Order_Status_Txt               = ('GenerationCompleted')
      AND Fee_Mapping_Definition.Document_Line_Series_Ref_Id  IN ( 7789, 7788,7596 )
      AND FEE_MAPPING_DEFINITION.DOCUMENT_TYPE_REF_ID          = 1099
      AND Document_Generation_Request.Product_Request_Id      IN
        (SELECT PRODUCT_REQUEST.PRODUCT_REQUEST_id
        FROM Deal.Disclosed_Cost_Allocation,
          Deal.Disclosed_Closing_Cost,
          DEAL.External_Order_Request,
          DEAL.PRODUCT_REQUEST,
          Deal.Scenario
        WHERE Disclosed_Cost_Allocation.Disclosed_Closing_Cost_Id = Disclosed_Closing_Cost.Disclosed_Closing_Cost_Id
        AND Disclosed_Closing_Cost.External_Order_Request_Id      = External_Order_Request.External_Order_Request_Id
        AND External_Order_Request.Deal_Id                        = Product_Request.Deal_Id
        AND product_request.scenario_id                           = scenario.scenario_id
        AND SCENARIO.SCENARIO_STATUS_TYPE_REF_ID                  = 7206
        AND product_request.servicing_loan_acct_num              IS NOT NULL
        AND product_request.servicing_loan_acct_num               = 0017498379
          --AND Disclosed_Cost_Allocation.Disclosed_Cost_Allocation_Id = 5095263
        )
      GROUP BY DISCLOSED_CLOSING_COST.DISCLOSED_CLOSING_COST_ID,
        External_Order_Status.Status_Updated_Tmstp,
        Reference_Data.Ref_Code,
        disclosed_cost_allocation.to_be_paid_amt
      order by 3 desc,
        1 DESC);
    
    Result:
    312     1302            1
    2000     1304-1399     1
    76     1303            1
    312     1302            1
    2000     1304-1399     1
    76     1303            1 
    
    
    Required output:
    312     1302            1
    2000     1304-1399     1
    76     1303            1
    312     1302            2
    2000     1304-1399     2
    76     1303            2
    THX
    Rod.

    Hey, Rod,

    My guess is that you want:

    , dense_rank () over (order by  tmstp  desc)  AS rn 
    

    RANK means you'll jump numbers when there is a link. For example, if all 3 rows have the exact same last tmstp, all 3 rows would be assigned number 1, GRADE would assign 4 to the next line, but DENSE_RANK attributes 2.

    "PARTITION x" means that you are looking for a separate series of numbers (starting with 1) for each value of x. If you want just a series of numbers for the entire result set, then do not use a PARTITION BY clause at all. (PARTITION BY is never required.)
    Maybe you want to PARTITIONNER IN cd. I can't do it without some examples of data, as well as an explanation of why you want the results of these data.
    You certainly don't want to PARTITION you BY the same expression ORDER BY; It simply means that all the lines are tied for #1.

    I hope that answers your question.
    If not, post a small example data (CREATE TABLE and only relevant columns, INSERT statements) for all of the tables involved and also publish outcomes from these data.
    Explain, using specific examples, how you get these results from these data.
    Simplify the problem as much as possible.
    Always tell what version of Oracle you are using.
    See the FAQ forum {message identifier: = 9360002}

    Published by: Frank Kulash, August 1, 2012 13:20

  • Deputy of analytical functions

    Hi all

    I'm writing a query without using the analytical functions.
    Analytical func using,.
    Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
    PL/SQL Release 11.2.0.2.0 - Production
    "CORE     11.2.0.2.0     Production"
    TNS for Linux: Version 11.2.0.2.0 - Production
    NLSRTL Version 11.2.0.2.0 - Production
    
    SELECT id, sal, rank() OVER (PARTITION BY ID ORDER BY SAL) rnk FROM 
    (SELECT 10 AS id, 100 AS sal FROM DUAL
        UNION ALL
        SELECT 10, 300 FROM DUAL
        UNION ALL
        SELECT 10, 400 FROM DUAL
        UNION ALL
        SELECT 20, 200 FROM DUAL
        UNION ALL
        SELECT 20, 200 FROM DUAL
        UNION ALL
        SELECT 20, 300 FROM DUAL
        UNION ALL
        SELECT 30, 100 FROM DUAL
        UNION ALL
        SELECT 40, 100 FROM DUAL
        UNION ALL
        SELECT 40, 200 FROM DUAL
        )
    Expected results. I want that these results without analytical functions.
    10     100     1
    10     300     2
    10     400     3
    20     200     1
    20     200     1
    20     300     3
    30     100     1
    40     100     1
    40     200     2

    Hello

    SamFisher wrote:
    Hi all

    I'm writing a query without using the analytical functions.

    Why? What is the problem with the analytical functions? You have Oracle 11.2. Use it. Do not act as you have Oracle 8.0.

    One way to do that is a scalar subquery:

    SELECT    id
    ,       sal
    ,       (
              SELECT  1 + COUNT (*)
              FROM    table_x
              WHERE   id          = x.id
              AND     sal     < x.sal
           )     AS rnk
    FROM      table_x  x
    ORDER BY  id
    ,            rnk
    ;
    

    But it is extremely inefficient. This is an example of textbood (perhaps literally) why RANK is so useful.

  • Need help with the analytic function

    I want to get the highest employee details and the 2nd highest employee for a particular service. But also the Department should have more than 1 employee.
    I tried the query and it gave me the correct results. But I wonder if there is another solution than to use the subquery.

    Here is the table and the query result:
    with t as
    (
    select 1 emp_id,3 mgr_id,'Rajesh' emp_name,3999 salary,677 bonus,'HR' dpt_nme from dual union
    select 2 ,3 ,'Gangz',4500,800,'Finance' from dual  union
    select 3 ,4 ,'Sid',8000,12000,'IT' from dual  union
    select 4 ,null,'Ram',5000,677,'HR' from dual  union
    select 5 ,4,'Shyam',6000,677,'IT' from dual union
    select 6 ,4 ,'Ravi',9000,12000,'IT' from dual   
    )
    select * from 
    (select emp_id, mgr_id, emp_name, dpt_nme, salary, row_number() over (partition by dpt_nme order by salary desc) rn from t where dpt_nme in 
    (select dpt_nme from t group by dpt_nme having count(*) > 1)) where rn < 3

    Hello

    You need a subquery, but you don't need more than that.
    Here's a way to eliminate the additional subquery:

    WITH     got_analytics     AS
    (
         SELECT  emp_id,     mgr_id,     emp_name, dpt_nme, salary
         ,     ROW_NUMBER () OVER ( PARTITION BY  dpt_nme
                                   ORDER BY          salary     DESC
                           )         AS rn
         ,     COUNT (*)     OVER ( PARTITION BY  dpt_nme
                                       )         AS dpt_cnt
         FROM     t
    )
    SELECT  emp_id,     mgr_id,     emp_name, dpt_nme, salary
    ,     rn
    FROM     got_analytics
    WHERE     rn     < 3
    AND     dpt_cnt     > 1
    ;
    

    Analytical functions are calculated after the clause WHERE is applied. Since we need to use the results of the analytical ROW_NUMBER function in a WHERE clause, which means that we have to calculate ROW_NUMBER in a subquery and use the results in the WHERE clause of the main query. We can call the COUNT function analytical in the same auxiliary request and use the results in the same WHERE clause of the main query.

    Would what results you if there is a link for the 2nd highest salary in some Department? For example, if you add this line to your sample data:

    select 7 ,3 ,'Sunil',8000,12000,'IT' from dual  union
    

    ? You can use RANK rather than ROW_NUMBER.

  • Try to use a function of Group on an analytic function

    Hello

    We use the Oracle 11.1.

    I have an analytic function that gives me the DENSE_RANK of lines groups. I would like to return the highest value of each group.

    The function looks like:
    DENSE_RANK( ) OVER (PARTITION BY METRIC ORDER BY sum(AEROBIC_EXERCISE_P1), COACHID)
    When I try to use:
    MAX(DENSE_RANK( ) OVER (PARTITION BY METRIC ORDER BY sum(AEROBIC_EXERCISE_P1), COACHID))
    I have get and error
    ORA-30483: window  functions are not allowed here
    Is it possible that I can do this?

    Hello

    Sorry, my mistake. You do not have an ORDER BY clause analytic it.

    COUNT (DISTINCT SUM (aerobic_exercise_p1)) OVER (PARTITION BY  metric)
    

    If you would post CREATE TABLE and INSERT statements, then I could test it.

  • Use of analytic functions

    Hi gurus,
    I ask someone to enlighten me on the analytical functions.
    I used the following query:
    select * from 
    (select filename,count(regexp_substr(filename,'.*era'))over(  partition by regexp_substr(filename,'.*era') ) cnt
     FROM 
    l_x12n_835_fileinfo where partitionnum=76000 and clntsysnum=76500 and radt>='01-JAN-2010')
    where cnt>1
    The sample result set is:
    FILENAME     CNT
    
    rsmedcalwa.20100105.chpwr.072.era     4
    rsmedcalwa.20100105.chpwr.072.era.1     4
    rsmedcalwa.20100105.chpwr.072.era.2     4
    rsmedcalwa.20100105.chpwr.072.era.3     4
    rsmedcalwa.20100105.chpwr.081.era     3
    rsmedcalwa.20100105.chpwr.081.era.1     3
    rsmedcalwa.20100105.chpwr.081.era.2     3
    rsmedcalwa.20100106.chpwr.088.era     3
    rsmedcalwa.20100106.chpwr.088.era.1     3
    rsmedcalwa.20100106.chpwr.088.era.2     3
    rsmedcalwa.20100108.chppr.363.era.3     4
    rsmedcalwa.20100108.chppr.363.era.1     4
    rsmedcalwa.20100108.chppr.363.era.2     4
    rsmedcalwa.20100108.chppr.363.era     4
    Now, I changed the query to:
    select * from 
    (select filename,count(regexp_substr(filename,'.*era'))over(  partition by regexp_substr(filename,'.*era') order by filename   ) cnt
     FROM 
    l_x12n_835_fileinfo where partitionnum=76000 and clntsysnum=76500 and radt>='01-JAN-2010')
    where cnt>1
    The result set has been
    FILENAME     CNT
    
    rsmedcalwa.20100105.chpwr.072.era.1     2
    rsmedcalwa.20100105.chpwr.072.era.2     3
    rsmedcalwa.20100105.chpwr.072.era.3     4
    rsmedcalwa.20100105.chpwr.081.era.1     2
    rsmedcalwa.20100105.chpwr.081.era.2     3
    rsmedcalwa.20100106.chpwr.088.era.1     2
    rsmedcalwa.20100106.chpwr.088.era.2     3
    rsmedcalwa.20100108.chppr.363.era.1     2
    rsmedcalwa.20100108.chppr.363.era.2     3
    rsmedcalwa.20100108.chppr.363.era.3     4
    rsmedcalwa.20100112.chpwr.175.era.1     2
    rsmedcalwa.20100112.chpwr.175.era.2     3
    (1) I don't understand how the addition of the order by clause changes the count. Could someone explain please?
    When I change this order by order of regexp_substr(filename,'.*era'), it gives me the correct number.

    My requirement is to check how many similar file names I.

    (2) if there are any other better elsewhere, please let me know.

    Hello

    Analytical functions still carried on in a window of the the result set, which can be smaller than the result set.
    If you have a PARTITION BY clause, the window for each row includes rows with the same values from all the PARTITION BY expressions.
    If you have an ORDER BY clause, the window includes that of a section of consecutive lines in the score, as defined by a windowing clause (in other words, LINES or KEEP them). The default value is "RANGE BETWEEN UNBOUNDED PRECEDING AND LINE CURRENT.

    In your case, if the analytical clause is:

    over(  partition by regexp_substr(filename,'.*era') )
    

    and the line you are looking at a filename = 'rsmedcalwa.20100105.chpwr.072.era.2', the window takes up the entire partition, in other words, all lines whose name includes "rsmedcalwa.20100105.chpwr.072.era". In other words, the window is identical to the partition, because theree is no ORDER BY clause.

    But if you add an ORDER BY clause:

    over(  partition by regexp_substr(filename,'.*era') order by filename   )
    

    then the window (potentially) decreases. Since there is no clause window, the default value 'RANGE BETWEEN UNBOUNDED PRECDING AND a CURRENT LINE' is used, which means that only the lines with a lower or equal to "rsmedcalwa.20100105.chpwr.072.era.2" file name (using the normal string comparison) will affect the results.

    The analytical ORDER BY clause is required for certain features (such as ROW_NUMBER) significance only in regard to certain commands. For the most part fucntions (including COUNTY), the ORDER BY clause is optional, and you do not have to use a. In this case, it seems that you do not want the effect of a smaller than the partition window, just so, do not use an ORDER byclause of Analytics for this function.

    Remember, the analytical ORDER byclause is completely independent the ORDER BY query clause. If you want the result presented in a certain order, use an ORDER BY clause at the end of the query. It will not change the results of the analytical functions.

  • 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)
    
  • How to use Group by in the analytic function

    I need to write the Department that has the minimum wage in a row. She must be with analytical function, but I have problem in group by. I can't use min() without group by.

    Select * from (min (sal) select min_salary, deptno, RANK() ON RN (ORDER BY sal CSA, CSA rownum) of the Group of emp by deptno) < 20 WHERE RN order by deptno;

    Published by: senza on 6.11.2009 16:09

    Hello

    senza wrote:
    I need to write the Department that has the minimum wage in a row. She must be with analytic function

    Therefore with an analytic function? Looks like it is a duty.

    The best way to get these results is with an aggregate, not analysis, function:

    SELECT      MIN (deptno) KEEP (DENSE_RANK FIRST ORDER BY sal)     AS dept_with_lowest_sal
    FROM      scott.emp
    ;
    

    Note that you do not need a subquery.
    This can be modififed if, for example, you want the lowest Department with the sal for each job.

    But if your mission is to use an analytical function, that's what you have to do.

    but I have problem in group by. I can't use min() without group by.

    Of course, you can use MIN without GROUP BY. Almost all of the aggregate (including MIN) functions have analytical equivalents.
    However, in this issue, you don't need to. The best analytical approach RANK only, not use MIN. If you ORDER BY sal, the lines with rank = 1 will have the minimum wage.

    Select * from (min (sal) select min_salary, deptno, RANK() ON RN (ORDER BY sal CSA, CSA rownum) of the Group of emp by deptno) WHERE the RN< 20="" order="" by="">

    Try to select plain old sal instead of MIN (sal) and get reid of the GROUP BY clause.

    Add ROWNUM in the ORDER BY clause is to make RANK return the same result as ROW_NUMBER, every time that it is a tie for the sal, the output will still be distinct numbers. which line gets the lower number will be quite arbitrary, and not necessarily the same every time you run the query. For example, MARTIN and WARD have exactly the same salary, 1250. The query you posted would assign rn = 4 to one of them and rn = 5 to another. Who gets 4? It's a toss-up. It could be MARTIN the first time you try, and WARD the next. (In fact, in a very small table like scott.emp, it probably will be consistent, but always arbitrary.) If this is what you want, it would be clearer and simpler just to use ROW_NUMEBR instead of RANK.

Maybe you are looking for