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.
KOk - 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
-Learnsequelsan 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,
SantoshHi 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
Pradnya07when 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,
Chrishere 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
ThanksHi,
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_typeSomething 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,
KartikThanks 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
RobertHopefully 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 GoyalHow 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 -
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 ? -
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.
-
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
-
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