Analytic Functions in CONNECT BY Queries

Can analytic functions be used in a CONNECT BY query? Are there limits?
This problem occurs in Oracle 11.1.0.6.0, 10.2 and 10.1.
Here is the presenting problem:
Starting with data like this:
CREATE TABLE     enrollment
(      name          VARCHAR2 (10)
,      coursenumber     NUMBER
INSERT INTO enrollment (name, coursenumber) VALUES ('Ted',      101);
INSERT INTO enrollment (name, coursenumber) VALUES ('Ted',      102);
INSERT INTO enrollment (name, coursenumber) VALUES ('Ted',      103);
INSERT INTO enrollment (name, coursenumber) VALUES ('Mary',      102);
INSERT INTO enrollment (name, coursenumber) VALUES ('Mary',      104);
INSERT INTO enrollment (name, coursenumber) VALUES ('Hiro',      101);
INSERT INTO enrollment (name, coursenumber) VALUES ('Hiro',      104);
INSERT INTO enrollment (name, coursenumber) VALUES ('Hiro',      105);
COMMIT;I'm trying to get cross-tab output like this:
NAME       TXT
Hiro         101            104  105
Mary              102       104
Ted          101  102  103without knowing before-hand what course numbers, or even how many course numbers, will be in the results.
My strategy was to use LPAD to make the course numbers always occupy 5 spaces.
If n "columns" needed to be left blank before the number, I wanted to add 5n extra spaces.
I tried this:
WITH     universe     AS
     SELECT     name
     ,     coursenumber
     ,     DENSE_RANK () OVER ( ORDER BY        coursenumber)     AS cnum
     ,     ROW_NUMBER () OVER ( PARTITION BY  name
                               ORDER BY          coursenumber
                       )                         AS snum
     FROM     enrollment
SELECT     name
,     REPLACE ( SYS_CONNECT_BY_PATH ( LPAD ( TO_CHAR (coursenumber)
                                          , 5 * (cnum - LAG (cnum, 1, 0)
                                                               OVER ( PARTITION BY  name
                                                                         ORDER BY          coursenumber
          )     AS txt
FROM     universe
WHERE     CONNECT_BY_ISLEAF     = 1
START WITH     snum     = 1
CONNECT BY     snum     = PRIOR snum + 1
AND          name     = PRIOR name
ORDER BY     name
;but the txt column was always NULL.
I tried showing some of the intermediate calculations:
WITH     universe     AS
     SELECT     name
     ,     coursenumber
     ,     DENSE_RANK () OVER ( ORDER BY        coursenumber)     AS cnum
     ,     ROW_NUMBER () OVER ( PARTITION BY  name
                               ORDER BY          coursenumber
                       )                         AS snum
     FROM     enrollment
SELECT     name
,     REPLACE ( SYS_CONNECT_BY_PATH ( LPAD ( TO_CHAR (coursenumber)
                                          , 5 * (cnum - LAG (cnum, 1, 0)
                                                               OVER ( PARTITION BY  name
                                                                         ORDER BY          coursenumber
          )     AS txt
,     coursenumber
,     cnum
,     LAG (cnum, 1, 0) OVER ( PARTITION BY  name
                                            ORDER BY          coursenumber
                     )      AS lag_cnum
FROM     universe
-- WHERE     CONNECT_BY_ISLEAF     = 1
START WITH     snum     = 1
CONNECT BY     snum     = PRIOR snum + 1
AND          name     = PRIOR name
ORDER BY     name
;and they all seemed reasonable:
NAME       TXT                            COURSENUMBER       CNUM   LAG_CNUM
Hiro                                               101          1          0
Hiro                                               104          4          1
Hiro                                               105          5          4
Mary                                               102          2          0
Mary                                               104          4          2
Ted                                                101          1          0
Ted                                                102          2          1
Ted                                                103          3          2but txt was still NULL.
I got around the problem by computing the LAG in a sub-query (see [this thread|http://forums.oracle.com/forums/message.jspa?messageID=3875566#3875566]), but I'd like to know why LAG didn't work in the CONNECT BY query, or at least within SYS_CONNECT_BY_PATH.
I've had other problems before trying to use analytic functions in CONNECT BY queries. Sometimes, the presence of an analytic function woudl cause CONNECT BY to never work, sometimes it would destroy the order of the output. (Sorry, I don't have those examples handy now.)
Are there limitations on using analytic functions in a CONNECT BY query?
is there a work-around other than computing the analytic functions in a sub-query?
Thanks.

how about
SQL> with temp as
  2  (select name
  3       , coursenumber
  4    from enrollment
  5  )
  6  , courses as
  7  (select distinct
  8          coursenumber
  9     from enrollment
10  )
11  select name
12       , replace (sys_connect_by_path (case when t_course is not null
13         then rpad (t_course, 8, ' ')
14         else rpad (' ', 8, ' ')
15         end, ';'), ';', ' ') scbp
16    from (
17  select t.name
18       , t.coursenumber t_course
19       , c.coursenumber c_course
20       , row_number() over (partition by t.name
21                                order by c.coursenumber
22                           ) rn
23    from temp  t partition by (name)
24    right outer
25    join courses c
26      on c.coursenumber = t.coursenumber
27  )
28   where connect_by_isleaf = 1
29   start with rn = 1
30   connect by rn = prior rn + 1
31   and name = prior name;
NAME       SCBP
Hiro        101                        104      105
Mary                 102               104
Ted         101      102      103

Similar Messages

  • Analytic function to retrieve a value one year ago

    Hello,
    I'm trying to find an analytic function to get a value on another row by looking on a date with Oracle 11gR2.
    I have a table with a date_id (truncated date), a flag and a measure. For each date, I have at least one row (sometimes 2), so it is gapless.
    I would like to find analytic functions to show for each date :
    sum of the measure for that date
    sum of the measure one week ago
    sum of the measure one year ago
    As it is gapless I managed to do it the week doing a group by date in a subquery and using a LAG with offset set to 7 on top of it (see below).
    However I'm struggling on how to do that for the data one year ago as we might have leap years. I cannot simply set the offset to 365.
    Is it possible to do it with a RANGE BETWEEN window clause? I can't manage to have it working with dates.
    Week :LAG with offset 7
    SQL Fiddle
    or
    create table daily_counts
      date_id date,
      internal_flag number,
      measure1 number
    insert into daily_counts values ('01-Jan-2013', 0, 8014);
    insert into daily_counts values ('01-Jan-2013', 1, 2);
    insert into daily_counts values ('02-Jan-2013', 0, 1300);
    insert into daily_counts values ('02-Jan-2013', 1, 37);
    insert into daily_counts values ('03-Jan-2013', 0, 19);
    insert into daily_counts values ('03-Jan-2013', 1, 14);
    insert into daily_counts values ('04-Jan-2013', 0, 3);
    insert into daily_counts values ('05-Jan-2013', 0, 0);
    insert into daily_counts values ('05-Jan-2013', 1, 1);
    insert into daily_counts values ('06-Jan-2013', 0, 0);
    insert into daily_counts values ('07-Jan-2013', 1, 3);
    insert into daily_counts values ('08-Jan-2013', 0, 33);
    insert into daily_counts values ('08-Jan-2013', 1, 9);
    commit;
    select
        date_id,
        total1,
        LAG(total1, 7) OVER(ORDER BY date_id) total_one_week_ago
      from
          select
            date_id,
            SUM(measure1) total1
          from daily_counts
          group by date_id
    order by 1;
    Year : no idea?
    I can't give a gapless example, would be too long but if there is a solution with the date directly :
    SQL Fiddle
    or add this to the schema above :
    insert into daily_counts values ('07-Jan-2012', 0, 11);
    insert into daily_counts values ('07-Jan-2012', 1, 1);
    insert into daily_counts values ('08-Jan-2012', 1, 4);
    Thank you for your help.
    Floyd

    Hi,
    Sorry, I;m not sure I understand the problem.
    If you are certain that there is at least 1 row for every day, then you can be sure that the GROUP BY will produce exactly 1 row per day, and you can use LAG (total1, 365) just like you already use LAG (total1, 7).
    Are you concerned about leap years?  That is, when the day is March 1, 2016, do you want the total_one_year_ago column to reflect March 1, 2015, which was 366 days earlier?  If that case, use
    date_id - ADD_MONTHS (date_id, -12)
    instead of  365.
    LAG only works with an exact number, but you can use RANGE BETWEEN with other analytic functions, such as MIN or SUM:
    SELECT DISTINCT
              date_id
    ,         SUM (measure1) OVER (PARTITION BY date_id)    AS total1
    ,         SUM (measure1) OVER ( ORDER BY      date_id
                                    RANGE BETWEEN 7 PRECEDING
                                          AND     7 PRECEDING
                                  )                       AS total1_one_week_ago
    ,         SUM (measure1) OVER ( ORDER BY      date_id
                                    RANGE BETWEEN 365 PRECEDING
                                          AND     365 PRECEDING
                                  )                       AS total1_one_year_ago
    FROM      daily_counts
    ORDER BY  date_id
    Again, use date arithmetic instead of the hard-coded 365, if that's an issue.
    As Hoek said, it really helps to post the exact results you want from the given sample data.  You're miles ahead of the people who don't even post the sample data, though.
    You're right not to post hundreds of INSERT statements to get a year's data.  Here's one way to generate sample data for lots of rows at the same time:
    -- Put a 0 into the table for every day in 2012
    INSERT INTO daily_counts (date_id, measure1)
    SELECT  DATE '2011-12-31' + LEVEL
    ,       0
    FROM    dual
    CONNECT BY LEVEL <= 366

  • Analytic Functions - Need resultset only in one select

    Hello Experts,
    Problem Definition: Using Analytic Function, get Total sales for the Product P1 and Customer C1 [Total sales for the customer itself] in one line. I want to restrict the ResultSet of the query to Product P1, please look at the data below, queries and problems..
    Data
    Customer Product Qtr Sales
    C1 P1 19991 100.00
    C1 P1 19992 125.00
    C1 P1 19993 175.00
    C1 P1 19994 300.00
    C1 P2 19991 100.00
    C1 P2 19992 125.00
    C1 P2 19993 175.00
    C1 P2 19994 300.00
    C2 P1 19991 100.00
    C2 P1 19992 125.00
    C2 P1 19993 175.00
    C2 P1 19994 300.00
    Problem, I want to display....
    Customer Product ProdSales CustSales
    C1 P1 700 1400
    But Without using outer query, i.e. please look below for the query that returns this reult with two select, I want this result in one query only..
    Select * From ----*** want to avoid this... ***----
    (Select Customer,Product,
    Sum(Sales) ProdSales,
    Sum(Sum(Sales)) Over(Partition By Customer) CustSales
    From t1
    Where customer='C1')
    Where
    Product='P1' ;
    Also, I want to avoid Hard coding of P1 in the select clause....
    I mean, I can do it in one shot/select, but look at the query below, it uses P1 in the select clause, which is No No!! P1 is allowed only in Where or Having ..
    Select Customer,Decode(Product, 'P1','P1','P1') Product,
    Decode(Product,'P1',Sales,0) ProdSales,
    Sum(Sum(Sales)) Over (Partition By Customer ) CustSales
    From t1
    Where customer='C1' ;
    This will get me what I want, but as I said earlier, I want to avoid using P1 in the
    Select clause..
    Goal is to Avoid using
    1-> Two Select/Outer Query/In Line Views
    2-> Product 'P1' in the Select clause...No hard coded product name in the select clause and group by clause..
    Thanks
    -Dhaval

    Select * From ----*** want to avoid this... ***----
    (Select Customer,Product,
    Sum(Sales) ProdSales,
    Sum(Sum(Sales)) Over(Partition By Customer)
    CustSales
    From t1
    Where customer='C1')
    Where
    Product='P1' ;
    Goal is to Avoid using
    1-> Two Select/Outer Query/In Line ViewsWhy?

  • Need valuable guidance to make a peformance oriented query, trying to replace unions with analytical function

    Hi,
       Please find below table structure and insert scritps. Requesting for vluable help.
    create table temp2 (col1 number,col2 varchar2(10),col3 number,col4 varchar2(20));
    insert into temp2 values (1,'a',100,'vvv');
    insert into temp2 values (2,'b',200,'www'); 
    insert into temp2 values (3,'c',300,'xxx');
    insert into temp2 values (4,'d',400,'yyy');   
    insert into temp2 values (5,'e',500,'zzz');
    insert into temp2 values (6,'f',600,'aaa');
    insert into temp2 values (7,'g',700,'bbb'); 
    insert into temp2 values (8,'h',800,'ccc');
    I am trying to get same output, what we get from below UNION query with ANALYTICAL Function.
    select * from temp2 where col1 in (1,2,3,4,5)
    union
    select * from temp2 where col1 in (1,2,5,6)
    union
    select * from temp2 where col1 in (1,2,7,8);
    I am seeking help by this dummy example to understand the concept, how can we use analytical functional over UNION or OUTER JOINS.
    In my exact query, I am using same table three times adding UNION clause. here also we scan temp2 three times, so for bulky tables using 'union'  would be hampering query's performance
    It means i go with three time scans of same table that is not performance oriented. With the help of above required concept, i will try to remove UNIONs from my exact query.
    Thanks!!

    Thanks for your time BluShadow and sorry as i think i couldn't make my query clear.
    I try it again. Below there are three queries, you may see all three queries are using same tables. Difference in all three queries are just few conditions, which makes all three queries diff with each other.
    I know, u cant run below query in your database, but i think it will convey my doubt to you. I have mentioned no. of rows with each clause and total i am getting 67 rows as my output. (Reason may be first n third query's result set are the subset of Second Query dataset)
    So i want to take all common rows as well as additional rows, if present in any of the query. This is getting easliy done with UNION clause but want to have it in other way as here my same is getting scanned again n again.
    SELECT
             START_TX.FX_TRAN_ID START_FX_TRAN_ID
            ,END_TX.FX_TRAN_ID END_FX_TRAN_ID
            ,START_TX.ENTERED_DT_TS
            ,USER
            ,START_TX.TRADE_DT
            ,START_TX.DEAL_NUMBER
            ,START_TX.FX_DEAL_TYPE
            ,START_TX.ORIENTATION_BUYSELL
            ,START_TX.BASE_CCY
            ,START_TX.BASE_CCY_AMT
            ,START_TX.SECONDARY_CCY
            ,START_TX.SECONDARY_CCY_AMT
            ,START_TX.MATURITY_DT
            ,START_TX.TRADE_RT
            ,START_TX.FORWARD_PTS              
            ,START_TX.CORPORATE_PIPS           
            ,START_TX.DEAL_OWNER_INITIALS      
            ,START_TX.CORPORATE_DEALER         
            ,START_TX.PROFIT_CENTER_CD
            ,START_TX.COUNTERPARTY_NM
            ,START_TX.COUNTERPARTY_NUMBER
      FROM
          (SELECT * FROM FX_TRANSACTIONS WHERE GMT_CONV_ENTERED_DT_TS >=  TO_DATE('20-Nov-2013 4:00:01 AM','DD-Mon-YYYY HH:MI:SS AM')) START_TX
           INNER JOIN
          (SELECT * FROM FX_TRANSACTIONS WHERE GMT_CONV_ENTERED_DT_TS <=  TO_DATE('20-Nov-2013 4:59:59 PM','DD-Mon-YYYY HH:MI:SS AM'))  END_TX
       ON START_TX.COUNTERPARTY_NM        = END_TX.COUNTERPARTY_NM         AND
          START_TX.COUNTERPARTY_NUMBER    = END_TX.COUNTERPARTY_NUMBER     AND
          START_TX.FX_DEAL_TYPE           = END_TX.FX_DEAL_TYPE            AND
          START_TX.BASE_CCY               = END_TX.BASE_CCY                AND
          START_TX.SECONDARY_CCY          = END_TX.SECONDARY_CCY           AND
          NVL(START_TX.CORPORATE_DEALER,'nullX')=NVL(END_TX.CORPORATE_DEALER,'nullX')       AND
          START_TX.ORIENTATION_BUYSELL='B'                                 AND 
          END_TX.ORIENTATION_BUYSELL='S'                                  AND
          START_TX.FX_TRAN_ID = 1850718                                  AND
         (START_TX.BASE_CCY_AMT           = END_TX.BASE_CCY_AMT          
          OR
          START_TX.SECONDARY_CCY_AMT      = END_TX.SECONDARY_CCY_AMT)        -- 10 Rows
    UNION
    SELECT
             START_TX.FX_TRAN_ID START_FX_TRAN_ID
            ,END_TX.FX_TRAN_ID END_FX_TRAN_ID
            ,START_TX.ENTERED_DT_TS
            ,USER
            ,START_TX.TRADE_DT
            ,START_TX.DEAL_NUMBER
            ,START_TX.FX_DEAL_TYPE
            ,START_TX.ORIENTATION_BUYSELL
            ,START_TX.BASE_CCY
            ,START_TX.BASE_CCY_AMT
            ,START_TX.SECONDARY_CCY
            ,START_TX.SECONDARY_CCY_AMT
            ,START_TX.MATURITY_DT
            ,START_TX.TRADE_RT
            ,START_TX.FORWARD_PTS              
            ,START_TX.CORPORATE_PIPS           
            ,START_TX.DEAL_OWNER_INITIALS      
            ,START_TX.CORPORATE_DEALER         
            ,START_TX.PROFIT_CENTER_CD
            ,START_TX.COUNTERPARTY_NM
            ,START_TX.COUNTERPARTY_NUMBER
      FROM
          (SELECT * FROM FX_TRANSACTIONS WHERE GMT_CONV_ENTERED_DT_TS >=  TO_DATE('20-Nov-2013 4:00:01 AM','DD-Mon-YYYY HH:MI:SS AM')) START_TX
           INNER JOIN
          (SELECT * FROM FX_TRANSACTIONS WHERE GMT_CONV_ENTERED_DT_TS <=  TO_DATE('20-Nov-2013 4:59:59 PM','DD-Mon-YYYY HH:MI:SS AM'))  END_TX
       ON START_TX.COUNTERPARTY_NM        = END_TX.COUNTERPARTY_NM         AND
          START_TX.COUNTERPARTY_NUMBER    = END_TX.COUNTERPARTY_NUMBER     AND
          START_TX.FX_DEAL_TYPE           = END_TX.FX_DEAL_TYPE            AND
          START_TX.BASE_CCY               = END_TX.BASE_CCY                AND
          START_TX.SECONDARY_CCY          = END_TX.SECONDARY_CCY           AND
          NVL(START_TX.CORPORATE_DEALER,'nullX')=NVL(END_TX.CORPORATE_DEALER,'nullX')  AND
          START_TX.FX_TRAN_ID = 1850718                                  AND
          START_TX.ORIENTATION_BUYSELL='B'                                 AND 
          END_TX.ORIENTATION_BUYSELL='S'                        --                                   67 Rows
    UNION 
    SELECT
             START_TX.FX_TRAN_ID START_FX_TRAN_ID
            ,END_TX.FX_TRAN_ID END_FX_TRAN_ID
            ,START_TX.ENTERED_DT_TS
            ,USER
            ,START_TX.TRADE_DT
            ,START_TX.DEAL_NUMBER
            ,START_TX.FX_DEAL_TYPE
            ,START_TX.ORIENTATION_BUYSELL
            ,START_TX.BASE_CCY
            ,START_TX.BASE_CCY_AMT
            ,START_TX.SECONDARY_CCY
            ,START_TX.SECONDARY_CCY_AMT
            ,START_TX.MATURITY_DT
            ,START_TX.TRADE_RT
            ,START_TX.FORWARD_PTS              
            ,START_TX.CORPORATE_PIPS           
            ,START_TX.DEAL_OWNER_INITIALS      
            ,START_TX.CORPORATE_DEALER         
            ,START_TX.PROFIT_CENTER_CD
            ,START_TX.COUNTERPARTY_NM
            ,START_TX.COUNTERPARTY_NUMBER
      FROM
          (SELECT * FROM FX_TRANSACTIONS WHERE GMT_CONV_ENTERED_DT_TS >=  TO_DATE('20-Nov-2013 4:00:01 AM','DD-Mon-YYYY HH:MI:SS AM')) START_TX
           INNER JOIN
          (SELECT * FROM FX_TRANSACTIONS WHERE GMT_CONV_ENTERED_DT_TS <=  TO_DATE('20-Nov-2013 4:59:59 PM','DD-Mon-YYYY HH:MI:SS AM'))  END_TX
       ON START_TX.COUNTERPARTY_NM        = END_TX.COUNTERPARTY_NM         AND
          START_TX.COUNTERPARTY_NUMBER    = END_TX.COUNTERPARTY_NUMBER     AND
          START_TX.FX_DEAL_TYPE           = END_TX.FX_DEAL_TYPE            AND
          START_TX.BASE_CCY               = END_TX.BASE_CCY                AND
          START_TX.SECONDARY_CCY          = END_TX.SECONDARY_CCY           AND
          NVL(START_TX.CORPORATE_DEALER,'nullX')=NVL(END_TX.CORPORATE_DEALER,'nullX') AND
          START_TX.ORIENTATION_BUYSELL='B'                                 AND 
          END_TX.ORIENTATION_BUYSELL='S'                                   AND
          START_TX.FX_TRAN_ID = 1850718                                  AND
            END_TX.BASE_CCY_AMT BETWEEN (START_TX.BASE_CCY_AMT - (START_TX.BASE_CCY_AMT * :PERC_DEV/100)) AND (START_TX.BASE_CCY_AMT + (START_TX.BASE_CCY_AMT * :PERC_DEV/100))        
            OR
            END_TX.SECONDARY_CCY_AMT BETWEEN (START_TX.SECONDARY_CCY_AMT - (START_TX.SECONDARY_CCY_AMT*:PERC_DEV/100) ) AND (START_TX.SECONDARY_CCY_AMT + (START_TX.SECONDARY_CCY_AMT*:PERC_DEV/100))
        );                                                       ---                              10 Rows

  • Restrict Query Resultset  which uses Analytic Function

    Gents,
    Problem Definition: Using Analytic Function, get Total sales for the Product P1
    and Customer C1 [Total sales for the customer itself] in one line.
    I want to restrict the ResultSet of the query to Product P1,
    please look at the data below, queries and problems..
    Data
    Customer Product Qtr Sales
    C1 P1 19991 100.00
    C1 P1 19992 125.00
    C1 P1 19993 175.00
    C1 P1 19994 300.00
    C1 P2 19991 100.00
    C1 P2 19992 125.00
    C1 P2 19993 175.00
    C1 P2 19994 300.00
    C2 P1 19991 100.00
    C2 P1 19992 125.00
    C2 P1 19993 175.00
    C2 P1 19994 300.00
    Problem, I want to display....
    Customer Product ProdSales CustSales
    C1 P1 700 1400
    But Without using outer query, i.e. please look below for the query that
    returns this reult with two select, I want this result in one query only..
    Select * From ----*** want to avoid this... ***----
    (Select Customer,Product,
    Sum(Sales) ProdSales,
    Sum(Sum(Sales)) Over(Partition By Customer) CustSales
    From t1
    Where customer='C1')
    Where
    Product='P1' ;
    Also, I want to avoid Hard coding of P1 in the select clause....
    I mean, I can do it in one shot/select, but look at the query below, it uses
    P1 in the select clause, which is No No!! P1 is allowed only in Where or Having ..
    Select Customer,Decode(Product, 'P1','P1','P1') Product,
    Decode(Product,'P1',Sales,0) ProdSales,
    Sum(Sum(Sales)) Over (Partition By Customer ) CustSales
    From t1
    Where customer='C1' ;
    This will get me what I want, but as I said earlier, I want to avoid using P1 in the
    Select clause..
    Goal is to Avoid using
    1-> Two Select/Outer Query/In Line Views
    2-> Product 'P1' in the Select clause...
    Thanks
    -Dhaval Rasania

    I don't understand goal number 1 of not using an inline view.
    What is the harm?

  • My first real analytic function... any unexpected results?

    Hello all. I have a table that contains transactions from bank accounts. The columns I am concerned with (I think) are the account number and the status date.
    The status date has the date that the transaction cleared through the bank. I would like a query that returns all rows for an account that have cleared since the last reconciliation of that account. (the reconciliation will occur monthly)
    This will produce some test data that replicates what we'll have in this table.
    DROP TABLE dave_test;
    DROP TABLE dave_test succeeded.
    CREATE TABLE dave_test AS
    SELECT level id, ROUND(TO_NUMBER(level), -1) account, TO_DATE('2007-08-01','YYYY-MM-DD') test_date
    FROM DUAL
    CONNECT BY LEVEL < 20 UNION ALL
    SELECT 21, 10, TO_DATE('2007-07-01','YYYY-MM-DD') FROM DUAL UNION ALL
    SELECT 22, 10, TO_DATE('2007-06-01','YYYY-MM-DD') FROM DUAL UNION ALL
    SELECT 23, 0, TO_DATE('2007-09-01', 'YYYY-MM-DD') FROM DUAL;
    CREATE TABLE succeeded.
    SELECT * FROM dave_test ORDER BY id;
    ID ACCOUNT TEST_DATE
    1 0 01-AUG-07
    2 0 01-AUG-07
    3 0 01-AUG-07
    4 0 01-AUG-07
    5 10 01-AUG-07
    6 10 01-AUG-07
    7 10 01-AUG-07
    8 10 01-AUG-07
    9 10 01-AUG-07
    10 10 01-AUG-07
    11 10 01-AUG-07
    12 10 01-AUG-07
    13 10 01-AUG-07
    14 10 01-AUG-07
    15 20 01-AUG-07
    16 20 01-AUG-07
    17 20 01-AUG-07
    18 20 01-AUG-07
    19 20 01-AUG-07
    21 10 01-JUL-07
    22 10 01-JUN-07
    23 0 01-SEP-07
    22 rows selected
    I have developed a query that returns accurate results for my test data. My request is this:
    Will you look over this query and see if there is a better way of doing things? This is my first real attempt with an analytic function, so I would appreciate some input on anything that looks like it could be improved. Also, perhaps some test cases that might produce results I haven't thought of.
    Thank you for your time.
    SELECT
      id
      ,account
      ,test_date
      ,max(date_sort)
    FROM
      SELECT
        id            id
        ,account      account
        ,test_date    test_date
        ,CASE DENSE_RANK() OVER(PARTITION BY account ORDER BY TRUNC(test_date, 'DD') DESC)
          WHEN 1 THEN TO_DATE('1', 'J')
          WHEN 2 THEN test_date
          ELSE NULL
        END           date_sort
       FROM
        dave_test
    WHERE
      account = &account_number
    HAVING
      test_date > MAX(date_sort)
    GROUP BY
      id
      ,account
      ,test_date
    ORDER BY
      idRun with 0 as account number:
    ID                     ACCOUNT                TEST_DATE                 MAX(DATE_SORT)           
    23                     0                      01-SEP-07                 01-JAN-13                
    1 rows selectedRun with 10 as account number
    ID                     ACCOUNT                TEST_DATE                 MAX(DATE_SORT)           
    5                      10                     01-AUG-07                 01-JAN-13                
    6                      10                     01-AUG-07                 01-JAN-13                
    7                      10                     01-AUG-07                 01-JAN-13                
    8                      10                     01-AUG-07                 01-JAN-13                
    9                      10                     01-AUG-07                 01-JAN-13                
    10                     10                     01-AUG-07                 01-JAN-13                
    11                     10                     01-AUG-07                 01-JAN-13                
    12                     10                     01-AUG-07                 01-JAN-13                
    13                     10                     01-AUG-07                 01-JAN-13                
    14                     10                     01-AUG-07                 01-JAN-13                
    10 rows selectedRun with 20 as account_number
    ID                     ACCOUNT                TEST_DATE                 MAX(DATE_SORT)           
    15                     20                     01-AUG-07                 01-JAN-13                
    16                     20                     01-AUG-07                 01-JAN-13                
    17                     20                     01-AUG-07                 01-JAN-13                
    18                     20                     01-AUG-07                 01-JAN-13                
    19                     20                     01-AUG-07                 01-JAN-13                
    5 rows selectedLet me know if I need to clarify anything.

    Sorry, Volder, for being unclear.
    Here is the table the query is based on.
    desc bank_account_transactions
    Name                           Null     Type         
    ID                             NOT NULL NUMBER(28)   
    BKA_ID                         NOT NULL NUMBER(28)   
    BKATC_ID                       NOT NULL NUMBER(28)   
    ST_TABLE_SHORT_NAME                     VARCHAR2(10) 
    KEY_VALUE                               NUMBER(28)   
    EDF_ID                                  NUMBER(28)   
    GLFS_ID                        NOT NULL NUMBER(28)   
    GLTT_ID                                 NUMBER(28)   
    AMOUNT                         NOT NULL NUMBER(11,2) 
    PAYMENT_NUMBER                          NUMBER(9)    
    BANK_SERIAL_NUMBER                      NUMBER(15)   
    PAYEE_NAME                              VARCHAR2(60) 
    STATUS                         NOT NULL VARCHAR2(1)  
    STATUS_DATE                             DATE         
    EFFECTIVE_DATE                 NOT NULL DATE         
    POSITIVE_PAY_DATE                       DATE         
    DATA_SOURCE                    NOT NULL VARCHAR2(1)  
    REPORTED_TO_ACCOUNT_OWNER      NOT NULL VARCHAR2(1)  
    PAYEE_BANK_ACCOUNT_NUMBER               NUMBER(30)   
    PAYEE_BANK_ABA_NUMBER                   NUMBER(9)    
    DESCRIPTION                             VARCHAR2(4000)
    DATE_CREATED                   NOT NULL DATE         
    CREATED_BY                     NOT NULL VARCHAR2(30) 
    DATE_MODIFIED                           DATE         
    MODIFIED_BY                             VARCHAR2(30) 
    25 rows selectedThe bka_id is the account number, status is 'C' for cleared checks and the status_date is the date the check cleared.
    When I reconcile, I set the status to 'C' and set the status_date to SYSDATE. So the "last reconciliation date" is stored in status_date.
    Like so
    ID    Account_No  status_date   
    1     10          05-04-07
    2     10          05-04-07
    3     10          05-04-07
    4     20          05-04-07
    5     20          05-04-07
    6     10          06-03-07
    7     10          06-03-07
    8     20          06-03-07
    9     10          07-05-07
    10    10          07-05-07In this example, account 10 was reconciled on May 5, June 3, and July 5. So the previous reconciliation date would be 06-03-07, and my report would return the transactions from 07-05-07.
    For account 20, it was reconciled on May 5 and June 3. The previous reconciliation date would be 05-04-07, and the transactions from 06-03-07 would be reported.
    Does this help?
    I appreciate your time.

  • Problem with SUM () analytic function

    Dear all,
    Please have a look at my problem.
    SELECT CURR, DT, AMT, RATE,
    SUM(AMT) OVER (PARTITION BY CURR ORDER BY DT) SUMOVER,
    sum( amt * rate) over (PARTITION BY CURR ORDER BY DT) / SUM(AMT) OVER (PARTITION BY CURR ORDER BY DT) avgrt
    FROM
    select 'CHF' CURR, ADD_MONTHS(TO_DATE('01-DEC-07'), LEVEL -1) DT, 100 * LEVEL AMT, 1 +  ( 5* LEVEL/100) RATE
    FROM DUAL CONNECT BY LEVEL < 10
    SQL> /
    CUR DT               AMT       RATE    SUMOVER      AVGRT
    CHF 01-DEC-07        100       1.05        100       1.05
    CHF 01-JAN-08        200        1.1        300 1.08333333
    CHF 01-FEB-08        300       1.15        600 1.11666667
    CHF 01-MAR-08        400        1.2       1000       1.15
    CHF 01-APR-08        500       1.25       1500 1.18333333
    CHF 01-MAY-08        600        1.3       2100 1.21666667
    CHF 01-JUN-08        700       1.35       2800       1.25
    CHF 01-JUL-08        800        1.4       3600 1.28333333
    CHF 01-AUG-08        900       1.45       4500 1.31666667
    Table Revaluation
    select 'CHF' CURR1, '31-DEC-07' DT , 1.08 RATE FROM DUAL UNION ALL
    select 'CHF' CURR1, '31-MAR-08' DT , 1.22 RATE FROM DUAL UNION ALL
    select 'CHF' CURR1, '30-JUN-08' DT , 1.38 RATE FROM DUAL
    CUR DT              RATE
    CHF 31-DEC-07       1.08
    CHF 31-MAR-08       1.22
    CHF 30-JUN-08       1.38.
    Problem is with the calculation of average rate.
    I want to consider the data in the revaluation table to be used in the calculation of
    average rate.
    So average rate for Jan-08 will be
    (100 * 1.08(dec revaluation rate) + 200 * 1.1 ) / (300) = 1.093333333
    for Feb-08
    (100 * 1.08(dec revaluation rate) + 200 * 1.1 + 300 * 1.15) / (600) = 1.121666667
    for mar-08
    (100 * 1.08(dec revaluation rate) + 200 * 1.1 + 300 * 1.15 + 400 * 1.2) / (1000) = 1.153
    for Apr-08
    (1000 * 1.22(Apr revaluation rate) + 500 * 1.25) /1500 = 1.23
    for May-08
    (1000 * 1.22(Apr revaluation rate) + 500 * 1.25 + 600 * 1.30 ) /2100 = 1.25
    and so on..
    Kindly advice

    Hi,
    The main thing in this problem is that for every dt you want to compute the cumulative total from previous rows using the formula
    SUM (amt * rate)
    But rate can be either the rate from the revaluation table or the rate from the main table. For evaluating prior dates, you wnat to use the most recent rate.
    I'm not sure if you can do this using analytic functions. Like Damorgan said, you should use a self-join.
    The query below gives you the results you requested:
    WITH
    revaluation     AS
         SELECT 'CHF' curr1, TO_DATE ('31-DEC-07', 'DD-MON-RR') dt, 1.08 rate     FROM dual     UNION ALL
         SELECT 'CHF' curr1, TO_DATE ('31-MAR-08', 'DD-MON-RR') dt, 1.22 rate     FROM dual     UNION ALL
         SELECT 'CHF' curr1, TO_DATE ('30-JUN-08', 'DD-MON-RR') dt, 1.38 rate     FROM dual
    original_data     AS
         select     'CHF'                              curr
         ,     ADD_MONTHS(TO_DATE('01-DEC-07'), LEVEL -1)     dt
         ,     100 * LEVEL                         amt
         ,     1 + ( 5* LEVEL/100)                    rate
         FROM     dual
         CONNECT BY     LEVEL < 10
    two_rates     AS
         SELECT     od.*
              SELECT     MAX (dt)
              FROM     revaluation
              WHERE     curr1     = od.curr
              AND     dt     <= od.dt
              )          AS r_dt
              SELECT     AVG (rate) KEEP (DENSE_RANK LAST ORDER BY dt)
              FROM     revaluation
              WHERE     curr1     = od.curr
              AND     dt     <= od.dt
              )          AS r_rate
         FROM     original_data     od
    SELECT     c.curr
    ,     c.dt
    ,     c.amt
    ,     c.rate
    ,     SUM (p.amt)          AS sumover
    ,     SUM     ( p.amt
              * CASE
                   WHEN     p.dt <= c.r_dt
                   THEN     c.r_rate
                   ELSE     p.rate
                END
         / SUM (p.amt)          AS avgrt
    FROM     two_rates     c
    JOIN     original_data     p     ON     c.curr     = p.curr
                        AND     c.dt     >= p.dt
    GROUP BY     c.curr,     c.dt,     c.amt,     c.rate
    ORDER BY     c.curr,     c.dt
    ;

  • SQL Analytical Functions in 9i

    Hi
    I am trying to determine of the SQL Analytical Functions in Oracle 9i like LAG, NTILE, PERCENT_RANK etc are part of Enterprise without OLAP installed.
    They will be very useful to a set of queries I am trying to build but I don't want to add OLAP to the mix if I can help it as the customer won't be OLAP enabled
    Cheers

    Hi
    I am trying to determine of the SQL Analytical Functions in Oracle 9i like LAG, NTILE, PERCENT_RANK etc are part of Enterprise without OLAP installed.
    They will be very useful to a set of queries I am trying to build but I don't want to add OLAP to the mix if I can help it as the customer won't be OLAP enabled
    Cheers

  • How can we write this in analytical function..

    select a.employee_id,a.last_name,b.count from employees a, (select manager_id, count(manager_id) as count from employees group by manager_id) b where a.employee_id=b.manager_id;
    As per my requirement I need each manager name and no of employees reporting to him... above query works.. Could anybody help to write the same using analytic function.... Hw this same can be written in effiect way??? (quick performance)
    Please also share the link to download some doc to have good understanding of analytical function..
    Thanks in advance....

    are you trying to do a hierarchical type of query?
    select ename, count(ename) -1 numr_of_emps_under_this_mgr  from  emp
    connect by  empno =prior mgr
    group by ename
    order by count(ename) desc ;
    ENAME     NUMR_OF_EMPS_UNDER_THIS_MGR
    KING     13
    BLAKE     5
    JONES     4
    CLARK     1
    FORD     1
    SCOTT     1
    ADAMS     0
    TURNER     0
    MARTIN     0
    JAMES     0
    SMITH     0
    MILLER     0
    ALLEN     0
    WARD     0Here is the table structure I used (I think you can download it from oracle somewhere)
    CREATE TABLE EMP
      EMPNO     NUMBER(4)                           NOT NULL,
      ENAME     VARCHAR2(10 BYTE),
      JOB       VARCHAR2(9 BYTE),
      MGR       NUMBER(4),
      HIREDATE  DATE,
      SAL       NUMBER(7,2),
      COMM      NUMBER(7,2),
      DEPTNO    NUMBER(2)
    SET DEFINE OFF;
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7369, 'SMITH', 'CLERK', 7902, TO_DATE('12/17/1980 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        800, 20);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
    Values
       (7499, 'ALLEN', 'SALESMAN', 7698, TO_DATE('02/20/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        1600, 300, 30);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
    Values
       (7521, 'WARD', 'SALESMAN', 7698, TO_DATE('02/22/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        1250, 500, 30);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7566, 'JONES', 'MANAGER', 7839, TO_DATE('04/02/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        2975, 20);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
    Values
       (7654, 'MARTIN', 'SALESMAN', 7698, TO_DATE('09/28/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        1250, 1400, 30);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7698, 'BLAKE', 'MANAGER', 7839, TO_DATE('05/01/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        2850, 30);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7782, 'CLARK', 'MANAGER', 7839, TO_DATE('06/09/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        2450, 10);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7788, 'SCOTT', 'ANALYST', 7566, TO_DATE('12/09/1982 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        3000, 20);
    Insert into EMP
       (EMPNO, ENAME, JOB, HIREDATE, SAL, DEPTNO)
    Values
       (7839, 'KING', 'PRESIDENT', TO_DATE('11/17/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        5000, 10);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
    Values
       (7844, 'TURNER', 'SALESMAN', 7698, TO_DATE('09/08/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        1500, 0, 30);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7876, 'ADAMS', 'CLERK', 7788, TO_DATE('01/12/1983 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        1100, 20);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7900, 'JAMES', 'CLERK', 7698, TO_DATE('12/03/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        950, 30);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7902, 'FORD', 'ANALYST', 7566, TO_DATE('12/03/1981 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        3000, 20);
    Insert into EMP
       (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO)
    Values
       (7934, 'MILLER', 'CLERK', 7782, TO_DATE('01/23/1982 00:00:00', 'MM/DD/YYYY HH24:MI:SS'),
        1300, 10);
    COMMIT;

  • Alternate for analytic functions

    Hello All,
    I'm trying to write a query without using analytic functions.
    Using Analytic func,
    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 these results without analytic 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

    Hi,
    SamFisher wrote:
    Thank You Frank. That was simple.
    I was trying to get the reults without using analytical functions. Just trying to improve my SQL skills. Yes, I admit that practicising using the wrong tools can improve your SQL skills, but I think there's a lot to be said for practising using the right tools, too.
    I tried all sort of things. I thought hierarchical query would do it but hard luck for me.Do you want to use a CONNECT BY query for this? Here's one way:
    WITH     got_max_level            AS
         SELECT       id
         ,       sal
         ,       MAX (LEVEL)     AS max_level
         FROM       table_x
         CONNECT BY NOCYCLE  id        = PRIOR id
              AND          sal       >= PRIOR sal
              AND     (   sal       >  PRIOR sal
                   OR  ROWID > PRIOR ROWID
         GROUP BY  id
         ,            sal
    ,     got_cnt          AS
         SELECT       id
         ,       sal
         ,       COUNT (*)     AS cnt
         FROM       table_x
         GROUP BY  id
         ,            sal
    SELECT       x.id
    ,       x.sal
    ,       l.max_level + 1 - c.cnt     AS rnk
    FROM       table_x        x
    JOIN       got_max_level  l  ON   x.id     = l.id
                         AND      x.sal     = l.sal
    JOIN       got_cnt      c  ON      x.id     = c.id
                         AND      x.sal     = c.sal
    ORDER BY  x.id
    ,            x.sal
    ;This is even less efficient, as well as more complicated, than the scalar sub-query solution.

  • Advantages and disadvantages of Analytical function

    Plz list out the advantages and disadvantages of normal queries and queries using analytical function (Performance wise)

    I'm not sure how you wish to compare?
    Analytical functions give you functionality that cannot otherwise be achieved easily in a lot of cases. They can introduce some performance degredation to a query but you have to compare on a query by query basis to determine if analytical functions or otherwise are the best solution for the issue. If it were as simple as saying that analytical functions are always slower than doing it without analytical functions, then Oracle wouldn't bother introducing them into the language.

  • Are analytic functions usefull only for data warehouses?

    Hi,
    I deal with reporting queries on Oracle databases but I don't work on Data Warehouses, thus I'd like to know if learning to use analytic functions (sql for anaylis such as rollup, cube, grouping, ...) might be usefull in helping me to develop better reports or if analytic functions are usually usefull only for data warehouses queries. I mean are rollup, cube, grouping, ... usefull also on operational database or do they make sense only on DWH?
    Thanks!

    Mark1970 wrote:
    thus does it worth learning them for improving report queries also not on DHW but on common operational databases?Why pigeonhole report queries as "+operational+" or "+data warehouse+"?
    Do you tell a user/manager that "<i>No, this report cannot be done as it looks like a data warehouse report and we have an operational database!</i>"?
    Data processing and data reporting requirements not not care what label you assign to your database.
    Simple real world example of using analytical queries on a non warehouse. We supply data to an external system via XML. They require that we limit the number of parent entities per XML file we supply. E.g. 100 customer elements (together with all their child elements) per file. Analytical SQL enables this to be done by creating "buckets" that can only contain 100 parent elements at a time. Complete process is SQL driven - no slow-by-slow row by row processing in PL/SQL using nested cursor loops and silly approaches like that.
    Analytical SQL is a tool in the developer toolbox. It would be unwise to remove it from the toolbox, thinking that it is not applicable and won't be needed for the work that's to be done.

  • Need analytic function suggestion

    Hi,
    I need advice related to analytic ( I think ) function in Oracle 9.
    create table testx ( id number, arr number, fore number, actual number, result_x number, is_first number);
    insert into testx values ( 1, null, null, 12, null , 0 );
    insert into testx values ( 2, null, null, 14 , null, 0 );
    insert into testx values ( 3, 4, 5, 16, 16, 1 );
    insert into testx values ( 4, 5, 5, 18, 16, 0 );
    insert into testx values ( 5, 5, 5, 20, 16, 0 );
    insert into testx values ( 6, 5, 5, 22, 16, 0 );
    insert into testx values ( 7, 5, 5, 24, 16, 0 );
    insert into testx values ( 8, 5, 5, 25, 16, 0 );
    insert into testx values ( 9, 5, 8, 25, 13, 0 );
    insert into testx values ( 10, 5, 8, 21, 10, 0 );
    insert into testx values ( 11, 5, 8, 19, 7, 0 );
    insert into testx values ( 12, 5, 8, 18, 4, 0 );
    I need ONE level query ( no subqueries ) which will calculate value stored in RESULT_X column.
    Rule for calculation is:
    1. when arr and fore columns are available first time then result_x = actual ( row with id = 3)
    2. in other case result_x = (previous value of result_x + arr - fore )
    3. order of records is stored in id column
    I have problem with calculating previous value of result_x since it should be available in next row calculation and dependents on other columns values.
    Thanks for help,
    Regards,
    Piotr

    Hi, Piotr,
    This produces the results you requested:
    SELECT       testx.*
    ,       SUM ( CASE
                  WHEN  is_first = 1
                  THEN  result_x
                  ELSE  arr - fore
                 END
               ) OVER (ORDER BY  id)     AS computed_result_x
    FROM      testx
    ORDER BY  id
    ;This relies on the fact that there is only one row where is_first=1, and that all the earlier rows have NULL as arr or fore.
    If that's not the case in your real data, then I don't think it's possible in SQL without sub-queries. Why can't you use a sub-query?
    The problem is that rows up to the one with is_first=1 have to be treated differently from rows after that point, so ithe CASE expression might need to know if a given row is before or after the one with is_first=1. If you need an analytic function to determine that, then you need a sub-query, becuase analytic functions can not be nested.
    You could use MODEL or a recursive WITH clause to get the results you want, but they require sub-querries.

  • BO4 - Oracle Analytic Function within agg_aware measure

    Hi,
    We can use an analytic function within idt tool and when in a measures by itself it parses ok.
    However when include in an agg_aware measure it gives an ORA-00937 not a single group group function.
    When create queries with the agg_aware measure behaves ok, generates sql ok and runs ok - please advise.
    Thanks

    Nice, am I coming in here to read the English docs again?

  • From analytical function to regular query

    Hi all,
    I was reading a tutorial for analytical function and i found something like this
    sum(princial) keep(dense_rank first order by d_date) over partition by (userid, alias, sec_id, flow, p_date)
    can somebody translate this into simple queries / subquery? i am aware that analytical function are faster but i would like to know
    how this can translate to regular query.
    can someone help me writing a regular query that will be produce same result as query above?
    . thanks
    Edited by: Devx on Jun 10, 2010 11:16 AM

    Hi,
    WITH CUSTOMERS AS
    SELECT 1 CUST_ID ,'NJ' STATE_CODE,1 TIMES_PURCHASED FROM DUAL UNION ALL
    SELECT 1,'CT',1 FROM DUAL UNION ALL
    SELECT 2,'NY',10 FROM DUAL UNION ALL
    SELECT 2,'NY',10 FROM DUAL UNION ALL
    SELECT 1,'CT',10 FROM DUAL UNION ALL
    SELECT 3,'NJ',2 FROM DUAL UNION ALL
    SELECT 4,'NY',4 FROM DUAL
    SELECT SUM(TIMES_PURCHASED) KEEP(DENSE_RANK FIRST ORDER BY CUST_ID ASC) OVER (PARTITION BY STATE_CODE) SUM_TIMES_PURCHASED_WITH_MIN,
           SUM(TIMES_PURCHASED) KEEP(DENSE_RANK LAST ORDER BY CUST_ID) OVER (PARTITION BY STATE_CODE) SUM_TIMES_PURCHASED_WITH_MAX,
           C.*
    FROM   CUSTOMERS C;
    SUM_TIMES_PURCHASED_WITH_MIN     SUM_TIMES_PURCHASED_WITH_MAX     CUST_ID     STATE_CODE     TIMES_PURCHASED
    11     11     1     CT     10
    11     11     1     CT     1
    1     2     3     NJ     2
    1     2     1     NJ     1
    20     4     4     NY     4
    20     4     2     NY     10
    20     4     2     NY     10The above given example is self explanatory, execute the SQL, you'll notice that in the first column the sum of TIMES_PURCHASED partitioned by state code of FIRST cust_id will be repeated for the STATE_CODE partition, in the second column, the sum of TIMES_PURCHASED partitioned by state code of LAST cust_id will be repeated for the STATE_CODE partition.
    HTH
    *009*
    Edited by: 009 on Jun 10, 2010 10:53 PM

Maybe you are looking for

  • HP cp2025dn printing problem

    hi there, i hope there is some help out there, since i have absolutely no idea what else i could try to make my printer work via airport, which has until now worked perfectly well via direct usb connect. via airport either way (ip or bonjour) print j

  • Unzip CS5 download. How?

    Unzip CS5 download. How? Its in z7 format...

  • Positioning multiple video tracks in Prem.Elements10

    Hi there, I'm new to video editing and to Adobe Premiere Elements 10 so apologies if this is a silly question... When I export my files into mpeg format, the size, shape and positioning of my video tracks does not match those on the elements screen.

  • Cannot reïnstall photoshop cc

    Deleted photoshop cc by mistake, I cannot find my photoshop cc in my app list. However it seems that I can perform updates for my photshop cc even if I don't have it anymore. I have a mac.

  • For uploading PDF (in php) if (!=application/pdf) {"No PDF"} gives error when trying to upload PDF. Why?

    In a php upload file I have inserted: if($_FILES['file']['type'] !="application/pdf"){ echo "Should be PDF";} exit; Even when trying to upload a PDF file the error message comes: Should be PDF. Earlier this worked fine. Maybe a bug in an update? Rega