Count distinct in case statement

SELECT A.P_ID,
B.P_NAME,
C.P_DESC,
SUM(CASE
WHEN A.DATE BETWEEN TRUNC(ADD_MONTHS(LAST_DAY(SYSDATE),-4) + 1) AND ADD_MONTHS(LAST_DAY(TO_DATE(SYSDATE)),-1)
AND A.M_ID IS NOT NULL
THEN 1
ELSE 0
END) AS COUNT,
SUM(CASE
WHEN A.DATE BETWEEN TRUNC(ADD_MONTHS(LAST_DAY(SYSDATE),-4) + 1) AND ADD_MONTHS(LAST_DAY(TO_DATE(SYSDATE)),-1)
AND A.M_ID IS NOT NULL
THEN COUNT(DISTINCT A.M_ID)
ELSE 0
END) AS UNIQUE_COUNT, /* Not possible */
SUM(CASE
WHEN A.DATE BETWEEN TRUNC(SYSDATE,'YEAR') AND ADD_MONTHS(LAST_DAY(TO_DATE(SYSDATE)),-1)
THEN A.AMT_1
ELSE 0
END) AS TOTAL_AMT_1,
SUM(CASE
WHEN A.DATE BETWEEN TRUNC(SYSDATE,'YEAR') AND ADD_MONTHS(LAST_DAY(TO_DATE(SYSDATE)),-1)
THEN A.AMT_2
ELSE 0
END) AS TOTAL_AMT_2
FROM TABLE_A A,
TABLE_B B,
TABLE_C C
WHERE A.P_ID = B.P_ID
AND B.PT_ID = C.PT_ID
GROUP BY A.P_ID,
B.P_NAME,
C.P_DESC
Hi,
This is a simplified version of my query.
I am trying to do 4 things here,
1. count A.M_ID
2. count distinct A.M_ID, this is where I have a problem.
3. and 4. Its just the sum from 2 diff columns.
Note that the dates for count and amt are different and I can't hard code them.
Can any one help me in the distinct count step?
This query is also running kinda slow.
So any suggestions, comments are very welcome.
Note: TABLE_A has 700 million recs, TABLE_B 4 million and TABLE_c is just 500 recs
Thanks!

Taking advantage of the fact that most aggregate functions ignore nulls, you could do something like:
SELECT a.p_id, b.p_name, c.p_desc,
       COUNT(CASE WHEN a.date BETWEEN TRUNC(ADD_MONTHS(LAST_DAY(sysdate),-4) + 1) AND
                                      ADD_MONTHS(LAST_DAY(TO_DATE(sysdate)),-1) AND
                       a.m_id IS NOT NULL THEN m_id END) AS countall,
       COUNT(DISTINCT CASE WHEN a.date BETWEEN TRUNC(ADD_MONTHS(LAST_DAY(sysdate),-4) + 1) AND
                                    ADD_MONTHS(LAST_DAY(TO_DATE(sysdate)),-1) AND
                     a.m_id IS NOT NULL THEN a.m_id END) AS unique_count, /* entirely possible */
       SUM(CASE WHEN a.date BETWEEN TRUNC(sysdate,'YEAR') AND
                                    ADD_MONTHS(LAST_DAY(TO_DATE(sysdate)),-1) THEN a.amt_1
                ELSE 0 END) AS total_amt_1,
       SUM(CASE WHEN A.DATE BETWEEN TRUNC(sysdate,'YEAR') AND
                                    ADD_MONTHS(LAST_DAY(TO_DATE(sysdate)),-1) THEN A.AMT_2
                ELSE 0 END) AS TOTAL_AMT_2
FROM table_a a, table_b b, table_c c
WHERE a.p_id = b.p_id and
      b.pt_id = c.pt_id
GROUP BY a.p_id, b.p_name, c.p_descThe two case statements inside the COUNT return either a.m_id or NULL. A simplified test case is:
SQL> WITH t as (
  2     SELECT 1 m_id, 9 dt FROM dual UNION ALL
  3     SELECT 1 m_id, 6 dt FROM dual UNION ALL
  4     SELECT 2 m_id, 9 dt FROM dual UNION ALL
  5     SELECT 2 m_id, 6 dt FROM dual UNION ALL
  6     SELECT 1 m_id, 5 dt FROM dual UNION ALL
  7     SELECT 2 m_id, 5 dt FROM dual UNION ALL
  8     SELECT null m_id, 9 dt FROM dual)
  9  SELECT count(CASE WHEN dt BETWEEN 6 and 9 THEN m_id end) cid,
10         count(distinct CASE WHEN dt BETWEEN 6 and 9 THEN m_id end) cdid
11  FROM t;
       CID       CDID
         4          2I'm not entirely sure that you actually need the a.m_id IS NOT NULL predicate in the CASE statements, but I left it to be safe.
John

Similar Messages

  • Count Distinct Wtih CASE Statement - Does not follow aggregation path

    All,
    I have a fact table, a day aggregate and a month aggregate. I have a time hierarchy and the month aggregate is set to the month level, the day aggregate is set to the day level within the time hierarchy.
    When using any measures and a field from my time dimension .. the appropriate aggregate is chosen, ie month & activity count .. month aggregate is used. Day & activity count .. day aggregate is used.
    However - when I use the count distinct aggregate rule .. the request always uses the lowest common denominator. The way I have found to get this to work is to use a logical table source override in the aggregation tab. Once I do this .. it does use the aggregates correctly.
    A few questions
    1. Is this the correct way to use aggregate navigation for the count distinct aggregation rule (using the source override option)? If yes, why is this necessary for count distinct .. what is special about it?
    2. The main problem I have now is that I need to create a simple count measure that has a CASE statement in it. The only way I see to do this is to select the Based on Dimensions checkbox which then allows me to add a CASE statement into my count distinct clause. But now the aggregation issue comes back into play and I can't do the logical table source override when the based on dimensions checkbox is checked .. so I am now stuck .. any help is appreciated.
    K

    Ok - I found a workaround (and maybe the preferred solution for my particular issue), which is - Using a CASE Statement with a COUNT DISTINCT aggregation and still havine AGGREGATE AWARENESS
    To get all three of the requirements above to work I had to do the following:
    - Create the COUNT DISTINCT as normal (counting on a USERID physically mapped column in my case)
    - Now I need to map my fact and aggregates to this column. This is where I got the case statement to work. Instead of trying to put the case statement inside of the Aggregate definition by using the checkbox 'Base on Dimension' (which didnt allow for aggregate awareness for some reason) .. I instead specified the case statement in the Column Mapping section of the Fact and Aggregate tables.
    - Once all the LTS's (facts and aggregates) are mapped .. you still have to define the Logical Table Source overrides in the aggregate tab of the count distinct definition. Add in all the fact and aggregates.
    Now the measure will use my month aggregate when i specify month, the day aggregate when i specify day, etc..
    If you are just trying to use a Count Distinct (no CASE satement needed) with Aggregate Awareness, you just need to use the Logical Table Source override on the aggregate tab.
    There is still a funky issue when using the COUNT aggregate type. As long as you dont map multiple logical table sources to the COUNT column it works fine and as expected. But, if you try to add in multiple sources and aggregate awareness it randomly starts SUMMING everything .. very weird. The blog in this thread says to check the 'Based on Dimension' checkbox to fix the problem but that did not work for me. Still not sure what to do on this one .. but its not currently causing me a problem so I will ignore for now ;)
    Thanks for all the help
    K

  • Efficiency of "Count(Distinct Case" in SQL

    Hi,
    Could you please let me know if "Count(Distinct Case" statement is efficient for a million rows or is there a better way to do it
    For example -this table below contains a set of customers with status flag as 'new' or 'existing'.
    CREATE TABLE tableA
    ( cust_id NUMBER
    , status VARCHAR(10)
    ,txn_id NUMBER
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 6433, 'New', 11);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 6433, 'New', 21);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 1234, 'existing', 31);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 1234, 'existing', 41);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 7654, 'New', 51);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 7654, 'New', 61);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 9999, 'existing', 71);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 8888, 'New', 81);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 8888, 'existing', 91);
    INSERT INTO tableA (cust_id, status,txn_id) VALUES ( 2121, 'New', 100);
    am using the below SQL to calculate the number of distinct customers with status 'New'.
    Select
    Count(Distinct Case When status = 'New' Then cust_id end) New_Cust_Cnt
    from tableA
    Regards
    -Learnsequel

    san wrote:
    Hello,
    Select
    Count(Distinct Case When status = 'New' Then cust_id end) New_Cust_Cnt
    from tableA
    _Use like this:_
    Select
    Count(cust_id) New_Cust_Cnt
    from tableA
    where status='new';And also you can create index on status you will get faster.
    Thanks,
    SanjeevaAny how you have to use DISTINCT keywork. Otherwise you will not get the correct results for the OP's data.

  • MDX -Children count function Not working in Case statement

    Hi,
    I am trying to create set when you slice with the Hierarchy member is leaf level , I want a output only that Leaf level .
    and When I slice with  the parent level , it has to give all the members below that parent level.
    But the problem here is when I select child member or leaf member , The first condition in the Case is not working
    WITH SET
    TESTSET AS
    CASE
    WHEN
     [Dimension].[Hierarchy].currentmember.children.count<0
    THEN
     [Dimension].[Hierarchy].currentmember
    ELSE
     DESCENDANTS([Dimension].[Hierarchy].Currentmember,,AFTER)
    END
    SELECT
    WBSSET ON 1,
    {} on 0
    FROM
     (SELECT {[Dimension].[Hierarchy].&[10]} ON COLUMNS FROM [CubeName])
    Thanks,
    Santosh

    Hi Santosh,
    I don't think Children count function not working in case statement, I have tested it on my local environment, here s the sample query for you reference.
    with member
    testset as
    case
    when
    [Geography].[Geography].currentmember.children.count<10
    then "X"
    else "OK"
    end
    select testset on 0,
    {[Geography].[Geography].[Country].members} on 1
    from
    [Adventure Works]
    In your scenario, the issue might be caused by the query isself, you can try to use IsLeaf Funcion to achieve your requirement. Please refer to the links below.
    http://msdn.microsoft.com/en-us/library/ms144932.aspx
    http://www.databasejournal.com/features/mssql/article.php/3633696/MDX-Operators-The-IsLeaf-Operator--Conditional-Logic-within--Calculations.htm
    http://www.mdxpert.com/Functions/MDXFunction.aspx?f=22
    Regards,
    Charlie Liao
    TechNet Community Support

  • Case statement to compare date and then count duration from only one date

    Hi All;
    I need to compare two dates and if date 1 > date 2 then consider date 2 and count its duration of appointments  from date 2
     case when CTE.scheduledstart  between [dbo].[DateTimeConvert] (new_dateofapplication) and 
             [dbo].[DateTimeConvert](ac.new_businessstartdate)
             then
            (CTE.scheduleddurationminutes)
     when  ( [dbo].[DateTimeConvert] (new_dateofapplication) >  [dbo].[DateTimeConvert](ac.new_businessstartdate))
            then
             [dbo].[DateTimeConvert](ac.new_businessstartdate)
            end as 'AFTERAPP',
    Any help on this is much appreciated
    I need to use case statement fro this
    Thanks
    Pradnya07

    when you say list of Appointments from Appointments table calculate duration from this date [dbo].[DateTimeConvert]
    do you mean find out duration from multiple record? or do you want
    suration for each row? also what represents this date here? Is it new_dateofapplication?
    can you show expected result for the data posted above?
    Please Mark This As Answer if it helps to solve the issue Visakh ---------------------------- http://visakhm.blogspot.com/ https://www.facebook.com/VmBlogs

  • Case statements to count Contact numbers

    Hi,
    I'm trying to use CASE IF or WHEN statements to count simple Contact numbers by owner or region. I need to count the following in separate fields of course:
    Number of contact type = Customers
    Number of Contact types = Propects
    Number of Contacts at each seniority level (6 levels)
    Number of contact validated (tick box)
    I presume I need to write a CASE statement that I can then use to Sum for each column but I'm struggling with CASE statements to apply an CASE IF Column equals 'Customer' then count 1 for example. Never done these before so any help or advice greatly appreciated.
    Contact type field is Contact."Contact Type"
    Contact Seniority is Contact.PICK_3
    Thanks,
    Chris

    here is an example:
    sum (case when contact type = 'Customers' then 1 else 0 end)
    Do the same for the second and forth in your list as above ;
    include the Contact.PICK_3 and # of contact fields in step 1;
    add region, owner, # of Customers, # of Prospects and # of validated in row section of your pivot view;
    add Contact.PICK_3 to column section;
    add # of contact to the measurement section.

  • Case Statement and Sequential Count

    I would like to obtain user input via a prompt and use what the user selects in my OBIEE Report case statement. I ve done the parameter part with a presentation variable.
    and a filter with the following.
    Recv Date is between @{Repair_Start_Date}{01-01-2013} and @{Repair_End_Date}{01-01-2013}
    Now I would like to have a sequential count of the records that meet the case statement, please advise.
    For example &START_DATE AND &END_DATE are user inputs:
    CASE when SHIP_DATE BETWEEN &START_DATE AND &END_DATE THEN 1
    Thanks

    Hi,
    Here is a way you could try.
    CASE when SHIP_DATE BETWEEN &START_DATE AND &END_DATE THEN RSUM(1) END
    So, what it does?
    Whenever the CASE statement is satisfied, it increments 1 by 1.
    Hope this helps.
    Thank you,
    Dhar

  • How do I use the CASE statement  in the where clause?

    Hello Everyone,
    I have 2 queries that do what I need to do but I am trying to learn how to use the CASE statement.
    I have tried to combine these 2 into one query using a case statement but don't get the results I need.
    Could use some help on how to use the case syntax to get the results needed.
    thanks a lot
    select segment_name,
    product_type,
    count (distinct account_id)
    FROM NL_ACCT
    where
    ind = 'N'
    and
    EM_ind = 'N'
    and product_type in ('TAX','PAY')
    and acct_open_dt between (cast('2006-01-17' as date)) and (cast('2006-01-17' as date) + 60)
    GROUP BY 1,2
    order by product_type
    select segment_name,
    product_type,
    count (distinct account_id)
    FROM NL_ACCT
    where
    ind = 'N'
    and
    EM_ind = 'N'
    and product_type not in ('TAX','PAY')
    and acct_open_dt between (cast('2006-01-17' as date)) and (cast('2006-01-17' as date) + 30)
    group by 1,2
    order by product_type

    Something like:
    SELECT segment_name, product_type,
           SUM(CASE WHEN account_id IN ('TAX','PAY') and
                         acct_open_dt BETWEEN TO_DATE('2006-01-17', 'yyyy-mm-dd') and
                               TO_DATE('2006-01-17', 'yyyy-mm-dd') + 60 THEN 1
                    ELSE 0 END) tax_pay,
           SUM(CASE WHEN account_id NOT IN ('TAX','PAY') and
                         acct_open_dt BETWEEN TO_DATE('2006-01-17', 'yyyy-mm-dd') and
                               TO_DATE('2006-01-17', 'yyyy-mm-dd') + 30 THEN 1
                    ELSE 0 END) not_tax_pay
    FROM NL_ACCT
    WHERE ind = 'N' and
          em_ind = 'N' and
          acct_open_dt BETWEEN TO_DATE('2006-01-17', 'yyyy-mm-dd') and
                               TO_DATE('2006-01-17', 'yyyy-mm-dd') + 60
    GROUP BY segment_name, product_type
    ORDER BY product_typeNote: You cannor GROUP BY 1,2, you need to explicitly name the columns to group by.
    HTH
    John

  • CASE statement in a dynamic page

    I have written a query using a CASE statement in the select portion to evaluate column values and produce a text string. The query runs fine in sql*plus, but when I attempt to add the code to a dynamic page and compile it, I get the following error message:
    ORA-06550: line 1, column 720:
    PLS-00103: Encountered the symbol "CASE" when expecting one of the following:
    ( - + mod null <an identifier>
    <a double-quoted delimited-identifier> <a bind variable>
    table avg count current max min prior sql stddev sum variance
    execute the forall time timestamp interval date
    <a string literal with character set specification>
    <a number> <a single-quoted SQL string> (WWV-11230)
    Critical Error in wwerr_api_error.get_errors! SQL Error Message: ORA-06502:
    PL/SQL: numeric or value error: character string buffer too small (WWV-)
    I am running oracle 8.1.7.1.0 using Portal 3.0.9.8.1
    I have written a function as a workaround, but would like to know why portal does not seem to like the "CASE" statement.
    Any suggestions would be greatly appreciated.

    Hi Chetan,
    I still get an error message even when I attempt to create a small dynamic page with your cursor. The error message is posted below. I am definitely putting the cursor declaration between <ORACLE></ORACLE> tags. Any Ideas?
    Thanks,
    Dan
    ORA-06550: line 1, column 215:
    PLS-00103: Encountered the symbol "CASE" when expecting one of the following:
    ( - + mod null <an identifier>
    <a double-quoted delimited-identifier> <a bind variable>
    table avg count current max min prior sql stddev sum variance
    execute the forall time timestamp interval date
    <a string literal with character set specification>
    <a number> <a single-quoted SQL string> (WWV-11230)
    Failed to parse as PORTAL30 - DECLARE CURSOR SPN_INMATE_INFO(V_SPN IN VARCHAR2) IS SELECT DISTINCT B.ENAME, B.ENAME||' '||B.ENAME F_NAME, B.DEPTNO, B.SAL, B.HIREDATE, B.SAL, B.EMPNO, B.HIREDATE, B.COMM, B.ENAME, CASE WHEN B.HIREDATE IS NULL THEN 'NO' WHEN B.HIREDATE IS NOT NULL AND B.SAL IS NOT NULL THEN 'NO' WHEN B.SAL IS NOT NULL AND B.HIREDATE IS NULL THEN 'YES' END RELEASED, C.DNAME, C.LOC, C.DEPTNO FROM SCOTT.EMP B, SCOTT.DEPT C WHERE C.DNAME NOT IN ('5397','6497','6498','6499','5011','42-9-44') AND C.LOC NOT IN ('M','F') AND B.ENAME != '00188547' AND B.DEPTNO = C.DEPTNO ORDER BY B.HIREDATE; BEGIN NULL; END; (WWV-08300)

  • Issue with referencing Presentation variables(Date cols) in Case statement

    Hi,
    I m trying to reference presentation variables created on a Date column in the case statement of one of the request's columns as shown below:
    case when "- Quote Details"."Creation Date" between '@{from}{1999-1-1}' and '@{until}{2999-1-1}' then "- Quote Metrics"."# of Quotes" end
    I m getting a view display error with the below error message:
    State: HY000. Code: 10058. [NQODBC] [SQL_STATE: HY000] [nQSError: 10058] A general error has occurred. [nQSError: 17001] Oracle Error code: 1861, message: ORA-01861: literal does not match format string at OCI call OCIStmtExecute
    SQL Issued: SELECT "- Quote Types"."Level2 Name" saw_0, case when "- Quote Details"."Creation Date" between '4/1/2009' and '4/15/2009' then "- Quote Metrics"."# of Quotes" end saw_1 FROM "(Unity) Quotes Catalog" WHERE "- Quote Details"."Creation Date" BETWEEN timestamp '2009-04-01 00:00:00' AND timestamp '2009-04-15 00:00:00' ORDER BY saw_0
    When I created the prompt on the date field I put the following formula in the prompt:
    cast("- Time".Day as DATE)
    When I apply a filter on the request using these variables it works fine.
    If anyone has faced this kind of issue earlier and have a resolution, please help me out.
    Thanks,
    Kartik

    Thanks Goran!!
    I've created prompts by selecting columns from the logical tables (i.e. I've selected 2 different cols of datatype DATE...inorder to assign 2 presentation variables).
    Yes I m using calendar widget for prompts.
    I haven't included any filter in my report. I m trying to display a metric when it satisfies the case statement.
    I will defintley go through the blogs you mentioned for better understanding.
    Thanks,
    Kartik
    Query fired on physical db:
    WITH
    SAWITH0 AS (select D1.c1 as c1,
    D1.c2 as c2,
    D1.c3 as c3,
    D1.c4 as c4,
    D1.c5 as c5
    from
    (select T192898.QLS_FIRST_ACAP_DT as c1,
    TO_DATE('3/2/2009','mm/dd/yyyy') as c2,
    TO_DATE('4/29/2009','mm/dd/yyyy') as c3,
    T188666.LEVEL2_NAME as c4,
    T188666.ID as c5,
    ROW_NUMBER() OVER (PARTITION BY T188666.ID, T192898.QLS_FIRST_ACAP_DT ORDER BY T188666.ID ASC, T192898.QLS_FIRST_ACAP_DT ASC) as c6
    from
    XXSLS_GBL_QTE_TYPES_V T188666,
    XXSLS_GBL_QTE_DTL_F T192898
    where ( T188666.ID = T192898.QUOTE_TYPE_ID )
    ) D1
    where ( D1.c6 = 1 ) ),
    SAWITH1 AS (select D1.c1 as c1,
    D1.c2 as c2,
    D1.c3 as c3
    from
    (select count(distinct T192898.QUOTE_HEADER_ID) as c1,
    T188666.LEVEL2_NAME as c2,
    T188666.ID as c3,
    ROW_NUMBER() OVER (PARTITION BY T188666.ID ORDER BY T188666.ID ASC) as c4
    from
    XXSLS_GBL_QTE_TYPES_V T188666,
    XXSLS_GBL_QTE_DTL_F T192898
    where ( T188666.ID = T192898.QUOTE_TYPE_ID )
    group by T188666.ID, T188666.LEVEL2_NAME
    ) D1
    where ( D1.c4 = 1 ) ),
    SAWITH2 AS (select D1.c1 as c1,
    D1.c2 as c2,
    D1.c3 as c3
    from
    (select case when SAWITH1.c2 is not null then SAWITH1.c2 when SAWITH0.c4 is not null then SAWITH0.c4 end as c1,
    case when SAWITH0.c1 between SAWITH0.c2 and SAWITH0.c3 then SAWITH1.c1 else NULL end as c2,
    case when SAWITH0.c5 is not null then SAWITH0.c5 when SAWITH1.c3 is not null then SAWITH1.c3 end as c3,
    ROW_NUMBER() OVER (PARTITION BY case when SAWITH0.c5 is not null then SAWITH0.c5 when SAWITH1.c3 is not null then SAWITH1.c3 end , case when SAWITH1.c2 is not null then SAWITH1.c2 when SAWITH0.c4 is not null then SAWITH0.c4 end ORDER BY case when SAWITH0.c5 is not null then SAWITH0.c5 when SAWITH1.c3 is not null then SAWITH1.c3 end ASC, case when SAWITH1.c2 is not null then SAWITH1.c2 when SAWITH0.c4 is not null then SAWITH0.c4 end ASC) as c4
    from
    SAWITH0 full outer join SAWITH1 On SAWITH0.c5 = SAWITH1.c3
    ) D1
    where ( D1.c4 = 1 ) )
    select SAWITH2.c1 as c1,
    SAWITH2.c2 as c2
    from
    SAWITH2
    order by c1

  • Conditional case statement help.!

    Hello Forum Members,
    I have a table with stores order along with order dates and other information. I have a requirement to write a query to get the nominations from that order's table according to the logic mentioned below.
    Nom1 =  Initial order date and next order within 7 days from initial order date then its considered as R1
    Nom2 = next activity within 7 seven on the same ord_id from its R1 date , this goes on as the order dates increases for same  or single ord_no
    Final Rn  is Count (Rn)
    Rn %-- Count(Rn)  / Count Distinct ( ord_no ) * 100
    Example data output:
    ORD_DATE
    ORD_ID
    1_of_x
    2_of_x
    3_of_x
    4_of_x
    5_of_x
    6_of_x
    Final RnX
    Rn%
    7/10/2013
    10095V1
    1
    0
    0
    0
    0
    0
    8/3/2013
    10095V1
    1
    0
    0
    0
    0
    0
    8/8/2013
    10095V1
    0
    1
    0
    0
    0
    0
    8/12/2013
    10095V1
    0
    0
    1
    0
    0
    0
    9/6/2013
    10095V1
    1
    0
    0
    0
    0
    0
    DDL:
    create table xx_ord_noms
    ord_no varchar(30),
    ord_date date,
    ord_id varchar2(30)
    Sample Data:
    INSERT INTO xx_ord_noms (ord_no, ord_date, ord_id) VALUES ('10091', TO_DATE('07/10/2013','MM/DD/YYYY'), '10091');
    INSERT INTO xx_ord_noms (ord_no, ord_date, ord_id) VALUES ('10091', TO_DATE('08/03/2013','MM/DD/YYYY'), '10091');
    INSERT INTO xx_ord_noms (ord_no, ord_date, ord_id) VALUES ('10091', TO_DATE('08/08/2013','MM/DD/YYYY'), '10091');
    INSERT INTO xx_ord_noms (ord_no, ord_date, ord_id) VALUES ('10091', TO_DATE('08/12/2013','MM/DD/YYYY'), '10091');
    INSERT INTO xx_ord_noms (ord_no, ord_date, ord_id) VALUES ('10091', TO_DATE('09/06/2013','MM/DD/YYYY'), '10091');
    commit;
    I was planning to doing something like this but I am not getting the logic for R1 .. R7
    select ord_no,
           ord_date,
           ord_id,
           prev_dt,
           (to_date(ord_date) - to_date(prev_dt)) data_diff,
           case
             when prev_dt is null or
                  (to_date(ord_date) - to_date(prev_dt)) < 7 then
              'R1'
             when (to_date(ord_date) - to_date(prev_dt)) > 7 THEN
              'R2'
             ELSE
              nULL
           END
      FROM (select a.*,
                   (SELECT MAX(tmp2.ord_date)
                      FROM xx_ord_noms tmp2
                     WHERE a.ord_id = tmp2.ord_id
                       AND tmp2.ord_date < a.ord_date) prev_dt
              from xx_ord_noms a);
    Could someone give me advises or suggestions on how we can get the expected output.
    Thanks in advance.

    LAG and LEAD are good when you want to look forward or back a fixed number of rows, but in this case you don't know how far back you'll need to go.
    I've got a solution. it calculates the Rn as a number, not a column position, but you can transform that with CASE statements if you want. I did it in two main steps:
    First I calculated the Rn by comparing the date of the current and previous row. To do that, I generated a row number using the row_number()  analytic function:
    select ord_no,
           ord_date,
           ord_id,
           numrow
    , Rn
    from xx_ord_noms
    model
      partition by (ord_no)
      dimension by (row_number() over (partition by ord_no order by ord_date)  numrow)
      measures (ord_date, 0 Rn, ord_id )
      rules update
        rn[1] = 1,
        rn[ANY] = CASE when trunc(ord_date[cv()]) - trunc(ord_date[cv() - 1])  < 7 then rn[cv()-1]+1 else 1 end
    ORD_NO     ORD_DATE             ORD_ID         NUMROW         RN
    10091      10-Jul-2013 00:00:00 10091               1          1
    10091      03-Aug-2013 00:00:00 10091               2          1
    10091      08-Aug-2013 00:00:00 10091               3          2
    10091      12-Aug-2013 00:00:00 10091               4          3
    10091      06-Sep-2013 00:00:00 10091               5          1
    Then I needed to identify all the rows of each series. I defined firstDt as the date of the first item in the series:
    firstDt[1] = ord_date[cv()]
    firstDt[ANY] = CASE when rn[cv()]= 1 then ord_date[cv()] else firstDt[cv()-1] end
    With that, the FinalRn is just an analytic max(rn) over (partition by firstDt)
    I'm not clear on what R% is. Your descriptions are unclear and I think they're inconsistent.
    select ord_no, ord_date, ord_id
    , Rn, finalRn, 100*finalRn/totCnt PCT1, 100 * totRn/totCnt PCT2
    , totRn
    from xx_ord_noms
    model
      partition by (ord_no)
      dimension by (row_number() over (partition by ord_no order by ord_date)  numrow)
      measures (ord_date, 0 Rn, ord_id, to_date(null) firstDt, 0 finalRn, 0 totRn, 0 totCnt )
      rules upsert all
        rn[1] = 1
      , rn[ANY] = CASE when trunc(ord_date[cv()]) - trunc(ord_date[cv() - 1])  < 7 then rn[cv()-1]+1 else 1 end
      , firstDt[1] = ord_date[cv()]
      , firstDt[ANY] = CASE when rn[cv()]= 1 then ord_date[cv()] else firstDt[cv()-1] end
      , finalRn[ANY] = max(rn) over (partition by firstDt)
      , totCnt[ANY] = count(*) over()
      , totRn[ANY] = count(case when rn = 1 then 1 else null end) over ()
    ORD_NO     ORD_DATE             ORD_ID             RN    FINALRN       PCT1       PCT2      TOTRN
    10091      10-Jul-2013 00:00:00 10091               1          1         20         60          3
    10091      03-Aug-2013 00:00:00 10091               1          3         60         60          3
    10091      08-Aug-2013 00:00:00 10091               2          3         60         60          3
    10091      12-Aug-2013 00:00:00 10091               3          3         60         60          3
    10091      06-Sep-2013 00:00:00 10091               1          1         20         60          3
    Regards,
    David

  • Case Statement ....please help :)

    Hi Guys\Gals,
    Just wondering if anyone can tell me the correct usage of the case statement:)
    I want to select counts for particular date ranges to come out as seperate columns.
    Is the Sql Server Case appliable in oracle circumstances?
    This is what im doing:
    select count(case when to_char(logtime,'MM') = '01' then source else 0 end) as January
    from messagetransactionlog
    SQL Error: ORA-00932: inconsistent datatypes: expected CHAR got NUMBER
    Then im getting something like from keyword not found!!
    Plz help :)
    Thanks
    Robert

    Hopefully im not boring people now :)
    can the case statement, as follows:
    count(case when logtime = '07-07' then UNIQUES else null end) as Jul
    be changed to only count distinct rows?
    count distinct (case when logtime = '07-07' then UNIQUES else null end) as Jul
    #SQL Error: ORA-00923: FROM keyword not found where expected
    count (case when logtime = '07-07' then distinct UNIQUES else null end) as Jul
    #SQL Error: ORA-00923: FROM keyword not found where expected

  • How to optimized Multiple CASE statement

    Hi..
    Somebody please help me out to use most optimized Multiple CASE statement in below example.. 
    Select
    CAST(COUNT(DISTINCT(CASE WHEN period_id <350 THEN period_id END)) AS DECIMAL(30,0))  AS Column1,                  CAST(COUNT(DISTINCT(CASE WHEN period_id >=351 AND period_id<=375 THEN period_id END))
    AS DECIMAL(30,0)) AS Column2,                                
    CAST(COUNT(DISTINCT(CASE WHEN period_id >=376 AND period_id<=400 THEN period_id END)) AS DECIMAL(30,0)) AS Column3,                             
    CAST(COUNT(DISTINCT(CASE WHEN period_id >=401 AND period_id<=450 THEN period_id END)) AS DECIMAL(30,0)) AS Column4,                             
    CAST(COUNT(DISTINCT(CASE WHEN period_id >=451 AND period_id<=575 THEN period_id END)) AS DECIMAL(30,0)) AS Column5,
    CAST(COUNT(DISTINCT(CASE WHEN pmc ='UVS' THEN pmc END)) AS DECIMAL(30,0)) AS Column6,                                
    CAST(COUNT(DISTINCT(CASE WHEN pmc ='VAL' THEN pmc END)) AS DECIMAL(30,0)) AS Column7                            
    FROM [Table1]
    Thanks in Advance,
    Deepak Goyal

    How is an index going to help in a query with no where clause or join?
    Rhetorical question but it brings to light the problem.  This query is going to produce a table/index scan precisely because there's no where clause.
    You need to change the way you are thinking about the problem.  The problem isn't that you need a better performing case statement, the problem is that you need to minimize the number of records you ask SQL Server to read from disk.  You do that
    by using a where clause or by joining to a smaller table.
    Here's one option which should give you the desired results while performing much better:
    create index idx_period_id on Table1 (period_id)
    create index idx_pmc on Table1 (pmc) include (period_id)
    select (select count(distinct period_id) from Table1 where period_id < 350) as Column1,
    (select count(distinct period_id) from Table1 where period_id between 351 and 375) as Column2,
    (select count(distinct period_id) from Table1 where period_id between 376 and 400) as Column3,
    (select count(distinct period_id) from Table1 where period_id between 401 and 450) as Column4,
    (select count(distinct period_id) from Table1 where period_id between 451 and 575) as Column5,
    (select count(distinct period_id) from Table1 where pmc = 'UVS') as Column6,
    (select count(distinct period_id) from Table1 where pmc = 'VAL') as Column7

  • Query cost and CASE statement

    Hi, I'm working on a performance issue for a customer.
    I'm tuning some suspect SQL that uses complex DECODE statements to perform IF/THEN/ELSE logic.
    I've taken a statement and rewritten it using CASE however what I've noticed is the cost of the query execution plan has increased dramatically as a result. N.B. I haven't changed the WHERE clause of the query as yet, just replaced one DECODE with the equivalent CASE.
    The db version is 9.2.0.4. Does anyone know of issues with the performance of CASE as opposed to DECODE. I'm wondering should I leave the DECODEs as is even though they're way too complicated.
    Tks,
    Paul.

    Here's an example of a DECODE:
    nvl(count(distinct decode
    (decode(sign(ords.dwh_created_date_id-:v_start_cycle_id),1,1,0,1,-1,0) *
    decode(sign(:v_end_cycle_id-ords.dwh_created_date_id),1,1,0,1,-1,0),1,ords.dwh_order_id,NULL)),0) calc1
    The equivalent CASE I've coded is:
    NVL(COUNT(DISTINCT(CASE WHEN (ords.dwh_created_date_id BETWEEN :v_start_cycle_id AND :v_end_cycle_id)
    THEN
    ords.dwh_order_id
    ELSE
    NULL
    END)),0) calc1
    I've been doing further testing with an amended WHERE clause and did run both CASE and DECODE versions. The performance difference between the two was negligible. So it seems (as I'd hoped) that the amendment of the execution path doesn't appear to be affected by CASE even though Oracle reports the query cost of it is higher.
    It is slightly confusing though. Is the query cost in this case a red herring ?

  • Nested Case Statement

    Hello,
    I need help implementing multiple Case Statements in a select statement. I can not get this to work in one statement.
    Select Statement
    select distinct
    allt.fk_jobcode_id as Job_Code,
    allt.fk_jobcode_descr as Classification,
    sum(allt.number_of_positions) as Number_Allotted,
    sum(number_of_positions) as Sum_Number_Allotted,
         dept.department_name|| ''||nvl2((CASE WHEN div.division_name <> 'N/A'
        THEN div.division_name 
      END),'/'||DIV.DIVISION_NAME||'',null) as Department_Division,
    allt.fund_type as Fund
    from tbl_allotment allt, tbl_department dept, tbl_division div
    where isdeleted <> 'Y'
    and ALLT.FK_DEPARTMENT_ID = dept.department_id
    and ALLT.FK_DIVISION_ID = div.division_id
    group by fk_jobcode_id, fk_jobcode_descr, fund_type, department_name, division_name
    HAVING (count(fk_jobcode_descr ) = 1)
    order by Classification asc, Department_Division asc1st CASE Statement combines the Department_Name and Division_Name values but does not display the Division_Name if the value is 'N/A'.
         dept.department_name|| ''||nvl2((CASE WHEN div.division_name <> 'N/A'
        THEN div.division_name 
      END),'/'||DIV.DIVISION_NAME||'',null) as Department_Division,value: Council Administrator's Office/Administration
    value: Council Administrator's Office/N/A will display as Council Administrator's Office
    I need to extend this now by using this CASE Statement, which displays the text 'Public Works' if the Department_Id = 00072.
         (CASE dept.department_id
         When '00072' then 'Public Works'
         Else dept.Department_Name
         End) as Department_Name, incorrect: Road Rehab Program/GLP Transportation Program Admin
    Should populate as: Public Works/GLP Transportation Program Admin
    select distinct
    allt.fk_jobcode_id as Job_Code,
    allt.fk_jobcode_descr as Classification,
    sum(allt.number_of_positions) as Number_Allotted,
    sum(number_of_positions) as Sum_Number_Allotted,
         dept.department_name|| ''||nvl2((CASE WHEN div.division_name <> 'N/A'
        THEN div.division_name 
      END),'/'||DIV.DIVISION_NAME||'',null) as Department_Division,
      (CASE dept.department_id
         When '00072' then 'Public Works'
        ELSE dept.Department_Name|| ''||nvl2((CASE WHEN div.division_name <> 'N/A'
        THEN div.division_name 
           END),'/'||DIV.DIVISION_NAME||'',null)
      END) as Department_Name1,
    allt.fund_type as Fund
    from tbl_allotment allt, tbl_department dept, tbl_division div
    where isdeleted <> 'Y'
    and ALLT.FK_DEPARTMENT_ID = dept.department_id
    and ALLT.FK_DIVISION_ID = div.division_id
    group by fk_jobcode_id, fk_jobcode_descr, fund_type, department_name, division_name, department_id
    HAVING (count(fk_jobcode_descr ) = 1)
    order by Classification asc, Department_Division ascbut once I modify the select statement I am only getting value 'Public Works' for Department_Division value. Does not populate the Division_Name data. Does anyone know how to combine these CASE Statements? Thanks for reading this Thread also.

    Hi,
    I think you want something like this:
    SELECT       ...
    ,       CASE
               WHEN  department_id = '00072'
               THEN  'Public Works'
               ELSE  dept.department_name
           END
           ||
           CASE
               WHEN  div.division_name != 'N/A'
               THEN  '/' || div.division_name
           END          AS department_name1
    ...Whenever you have a problem, post a little sample data (CREATE TABLE and INSERT statements, relevant columns only) from all tables.
    Also post the results you want from that data, and an explanation of how you get those results from that data, with specific examples.
    Always say which version of Oracle you're using.

Maybe you are looking for

  • Do I need to buy a base for Airport to work?

    I acquired my grandmother's iMac that she's had for just under a year and I can't seem to figure out the internet connection. My two roommates and I all have Dell PC's/laptops and use Comcast wireless internet. I'm having trouble connecting with the

  • Hello I have Adobe Flash Player installed but cannot enable it.

    Hello I have Adobe Flash Player installed but cannot enable it.

  • Button to extract pages

    myexportFunc = app.trustedFunction(function(){ ////Get Naming Convention var cRtn = app.response('Enter naming convention for section:'); ////Save to current location. Get path of current doc var testing = this.path; var test = testing.split('/'); va

  • Rotated photos--fine in preview, wrong in iphoto

    Hi, I've looked through help for this, and can't find anyone with the same problem. Can anyone help? I imported about 500 photos from my Canon S1 using Image Capture, erased the card, and then found that the camera hadn't auto-rotated the photos (the

  • Facelet support in ADF 11g

    Hi all, I am wondering if Facelet is officially supported in ADF 11g (currently looking at 11.1.1.3) I searched through both "Fusion Developer's Guide" and "Web User Interface Developer's Guide", neither guide talks about facelet support. Any advice