My select query before changes was:
select * from abc
WHERE
CASE WHEN NVL(gr.Rgid,a.pc) = 'CRA' THEN
CASE WHEN NVL(TRUNC(a.DATEOFSFROM),TO_DATE('99991231','YYYYMMDD')) >= TO_DATE('20170101','YYYYMMDD') THEN 'Y' ELSE 'N' END
When gr.Rgid='021SHOP' THEN
CASE WHEN TRUNC(a.datep) <= to_date('20190630', 'YYYYMMDD') then 'Y' ELSE 'N' end
ELSE 'Y' END = 'Y'
I need new case when statement,so I added:
select * from abc
WHERE
CASE WHEN NVL(gr.Rgid,a.pc) = 'CRA' THEN
CASE WHEN NVL(TRUNC(a.DATEOFSFROM),TO_DATE('99991231','YYYYMMDD')) >= TO_DATE('20170101','YYYYMMDD') THEN 'Y' ELSE 'N' END
When gr.Rgid='021SHOP' THEN
CASE WHEN TRUNC(a.datep) <= to_date('20190630', 'YYYYMMDD') then 'Y' ELSE 'N' end
ELSE 'Y' END = 'Y'
CASE WHEN NVL(gr.Rgid,a.pc) IN ('01FLW','002FE') then
a.datep <=to_date('20180131', 'YYYYMMDD') END;
I added these statement from my side
CASE WHEN NVL(gr.Rgid,a.pc) IN ('01FLW','002FE') then
a.datep <=to_date('20180131', 'YYYYMMDD') END;
But I am getting error:ORA-00905:missing keyword error. I searched these similar question but I only see is case when used is being wrong.But from my analysis,the case when I am using in right.
You didn't say what exactly should be the outcome so I guessed. Note comments within code, which contains new CASE:
SELECT *
FROM abc
WHERE CASE
WHEN NVL (gr.Rgid, a.pc) = 'CRA'
THEN
CASE
WHEN NVL (TRUNC (a.DATEOFSFROM),
TO_DATE ('99991231', 'YYYYMMDD')) >=
TO_DATE ('20170101', 'YYYYMMDD')
THEN
'Y'
ELSE
'N'
END
WHEN gr.Rgid = '021SHOP'
THEN
CASE
WHEN TRUNC (a.datep) <= TO_DATE ('20190630', 'YYYYMMDD')
THEN
'Y'
ELSE
'N'
END
-- your new WHEN begins here ...
WHEN NVL (gr.Rgid, a.pc) IN ('01FLW', '002FE')
THEN
CASE
WHEN a.datep <= TO_DATE ('20180131', 'YYYYMMDD')
THEN 'Y'
ELSE 'N'
END
-- ... and ends here
ELSE
'Y'
END =
'Y'
Your query:
select * from abc
WHERE
CASE WHEN NVL(gr.Rgid,a.pc) = 'CRA' THEN
CASE WHEN NVL(TRUNC(a.DATEOFSFROM),TO_DATE('99991231','YYYYMMDD')) >= TO_DATE('20170101','YYYYMMDD') THEN 'Y' ELSE 'N' END
When gr.Rgid='021SHOP' THEN
CASE WHEN TRUNC(a.datep) <= to_date('20190630', 'YYYYMMDD') then 'Y' ELSE 'N' end
ELSE 'Y' END = 'Y'
that's all ok.
When adding CASE WHEN NVL(gr.Rgid,a.pc) IN ('01FLW','002FE') then a.datep <=to_date('20180131', 'YYYYMMDD') END to the end you're screwing up the syntax.
Syntax: where a = b or c = d.
You wrote where a = b and then added c so it becomes where a = b c.
Add your new line with a AND or OR and get a value to compare it to, like
SELECT * FROM ABC
WHERE
CASE WHEN NVL(gr.Rgid,a.pc) = 'CRA' THEN
...
ELSE 'Y' END = 'Y'
-- new here
AND CASE WHEN NVL(gr.Rgid,a.pc) IN ('01FLW','002FE') AND a.datep <=to_date('20180131', 'YYYYMMDD')
then 'true'
ELSE 'false'
END = 'true';
I also transformed your case statement to a equation like a = b by moving your condition into the WHEN-Block and then comparing if it's the first when block or not by ... END = 'true'.
You cannot add where statements within a case expression like you did.
Please note that I wrote this without actual verification, so syntac errors may still occur.
Related
I'm getting ORA- 00936 missing expression error near > symbol while trying to run this request :
SELECT contract_ref_no,
component
FROM some_table
WHERE Contract_ref_no = '123'
AND component = 'ABC'
AND end_date
(CASE WHEN NVL(l_neg_esn_allowed,'N') = 'N'
THEN
> greatest(nvl(l_conv_eff_date, l_contract_vdate),
l_contract_vdate)
ELSE
>=
greatest(nvl(l_conv_eff_date, l_contract_vdate),
l_contract_vdate)
END)
How can I fix it?
With a bit reformulation based on the rules of Aristoteles you may write
you allways want the end_date is greather than your greatest expression
OR
in the else case NVL(l_neg_esn_allowed,'N') != 'N' thay may be equal
Predicate
...
AND (
end_date > greatest(nvl(l_conv_eff_date, l_contract_vdate), l_contract_vdate)
OR
NVL(l_neg_esn_allowed,'N') != 'N' and end_date = greatest(nvl(l_conv_eff_date, l_contract_vdate), l_contract_vdate)
)
which is the same as the predicate below that more resembles your original intention
....
AND (
NVL(l_neg_esn_allowed,'N') = 'N' AND end_date > greatest(nvl(l_conv_eff_date, l_contract_vdate),l_contract_vdate)
OR
NVL(l_neg_esn_allowed,'N') != 'N' AND end_date >= greatest(nvl(l_conv_eff_date, l_contract_vdate),l_contract_vdate)
)
You can change your case statement to -
SELECT contract_ref_no,
component
FROM some_table
WHERE Contract_ref_no = '123'
AND component = 'ABC'
AND CASE WHEN NVL(l_neg_esn_allowed,'N') = 'N'
AND end_date > greatest(nvl(l_conv_eff_date, l_contract_vdate),
l_contract_vdate) THEN
1
WHEN end_date >= greatest(nvl(l_conv_eff_date, l_contract_vdate),
l_contract_vdate) THEN
1
END = 1;
The SQL query that you write have syntax error.
The THEN > something can't work : Superior to what ? Same with the >= after, superior or equals to what ?
So, you should have something like column > value, such as you will have column = value or column LIKE 'my val'.
Finally, I suggest you to use this code:
SELECT contract_ref_no,
component
FROM some_table
WHERE Contract_ref_no = '123'
AND component = 'ABC'
AND end_date
(CASE WHEN NVL(l_neg_esn_allowed,'N') = 'N'
THEN some_date > greatest(nvl(l_conv_eff_date, l_contract_vdate),
l_contract_vdate)
ELSE some_date >= greatest(nvl(l_conv_eff_date, l_contract_vdate),
l_contract_vdate)
END)
I am new to Oracle and was hoping someone could help me.
I have this stored procedure:
procedure ListCatalogues(P_CUR out sys_refcursor,
P_CATALOGUENAME varchar2 default '%',
P_LIMIT number,
P_MEMBERS number default -1) is
begin
open P_CUR for
select *
from ( select h.catalogueid id,
h.cataloguename name,
case
when h.uniquecatalogue = 'N'
then 1
else 0
end includeproducts,
case
when h.active = 'Y'
then 1
else 0
end active,
case
when h.ownbrandedlabels = 'Y'
then 1
else 0
end ownlabels,
( select count(*)
from cc_custprofiles t
where t.catalogueid = h.catalogueid
) members
from cc_ob_catalogueheader h
where upper(h.cataloguename) like upper('%'||P_CATALOGUENAME||'%')
and (select count(*) from cc_custprofiles t where t.catalogueid = h.catalogueid) >= P_MEMBERS
order by h.catalogueid
)
where rownum <= P_LIMIT;
end ListCatalogues;
As you can see, it accepts a P_LIMIT parameter which allows for limiting the results returned. This is fine, but I want to expand on it a little.
If the limit is 10, then return 10 rows, but if the limit is 0, return everything. Can someone help me change the query to match my criteria?
I managed this after a bit of looking around:
where rownum <= case when P_LIMIT = 0 then rownum else P_LIMIT end;
I have a table like "Emp_Info", For the below output i have used "two" SELECT Statements, I want work that using ONE SELECT STATEMENT.
select count(*) into cnt
from emp_info t
where upper(trim(t.email)) = upper(trim(field1value))
and t.company_id = companyId;
select
(case when cnt1 > 0 then 'YES' else 'NO' end) into val_acc
from (
select count(*) cnt1 from
emp_info t
where upper(trim(t.email)) = upper(trim(field1value))
and (t.account_expiry_dt is null or t.account_expiry_dt >= sysdate)
and t.company_id = companyId
);
if cnt = 0 then
raise_application_error(-20002, 'User does not exist');
elsif cnt > 1 then
raise_application_error(-20003, 'Duplicate records found');
elsif val_acc = 'NO' then
raise_application_error(-20004, 'Account has expired');
else
/* some logic */
end if;
end;
may be this help you
select count(*),
CASE WHEN
sum( CASE when t.account_expiry_dt is null or t.account_expiry_dt >= sysdate then 1 else 0 end) > 0 then 'YES'
else 'NO'
END
into cnt, val_acc
from emp_info t
where upper(trim(t.email)) = upper(trim(field1value))
and t.company_id = companyId;
simple demo:
with emp_info(login,username) as (select 'test', 'test' from dual union
select 'TEst', 'TEst' from dual )
select count(*) emp_count,
CASE when sum( CASE WHEN login like '%st%' then 1 else 0 end) > 0 then 'Y' else 'N' end emp_flag,
sum( CASE WHEN login like '%st%' then 1 else 0 end) emp_flag_count,
CASE when sum( CASE WHEN login like '%te%' then 1 else 0 end) > 0 then 'Y' else 'N' end emp_flag1,
sum( CASE WHEN login like '%te%' then 1 else 0 end) emp_flag_count1,
CASE when sum( CASE WHEN login like '%TE%' then 1 else 0 end) > 0 then 'Y' else 'N' end emp_flag2,
sum( CASE WHEN login like '%TE%' then 1 else 0 end) emp_flag_count2
from emp_info
answer if it helped you
Hi Gurus I am getting the error ORA-01732: data manipulation operation not legal on this view
when executing the below query
UPDATE (SELECT CR.AMOUNT AS AMOUNT,
CASE
WHEN MRG.AMOUNT_USD=0
THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END AS AMOUNT_BILAT,
CR.ISUPDATED
FROM CRS_TT_BILAT_EXCL_MERGE1 MRG,CRS_T_CURRENT_RATES1 CR
WHERE SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND CR.ISUPDATED <> 'Y'
AND ROWNUM = 1)
SET AMOUNT = AMOUNT_BILAT;
CR.ISUPDATED = 'Y';
I have simplified the above code from the below query
UPDATE CRS_T_CURRENT_RATES1 CR
SET CR.AMOUNT =
(SELECT
CASE
WHEN MRG.AMOUNT_USD=0
THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END
FROM CRS_TT_BILAT_EXCL_MERGE1 MRG
WHERE SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND ROWNUM = 1),
CR.ISUPDATED = 'Y'
WHERE EXISTS
(SELECT 1 FROM CRS_TT_BILAT_EXCL_MERGE1 MRG WHERE MRG.DNIS_CD = SUBSTR(CR.DNIS_CD, 1,3) AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID )
AND
CR.ISUPDATED <> 'Y';
I was trying to optimize the 2nd query, since the second query uses two selects i was trying to replace that with a single query. Can any one please help me on this?
MERGE statement with selecting 1st row for each (AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID) - ROWNUM=1 condition from your query:
MERGE INTO CRS_T_CURRENT_RATES1 CR
USING (SELECT * FROM (
SELECT AMOUNT_USD,
DNIS_CD,
PRODUCT_CUST_ID
ROW_NUMBER() OVER (PARTITION BY AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID ORDER BY 1) AS ORD_NO
FROM CRS_TT_BILAT_EXCL_MERGE1
) WHERE ORD_NO = 1
) MGR
ON CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID AND
SUBSTR(CR.DNIS_CD,1,3)=MRG.DNIS_CD
WHEN MATCHED THEN
UPDATE SET CR.AMOUNT = (CASE
WHEN MRG.AMOUNT_USD=0 THEN CR.AMOUNT
ELSE MRG.AMOUNT_USD
END),
ISUPDATED = 'Y'
WHERE ISUPDATED <> 'Y';
UPDATE: Using MERGE and ROWNUM won't work.
MERGE can help you avoid repeating SQL:
MERGE INTO CRS_T_CURRENT_RATES1 CR
USING
(
SELECT AMOUNT_USD, DNIS_CD, PRODUCT_CUST_ID
FROM CRS_TT_BILAT_EXCL_MERGE1
) MRG
ON
(
SUBSTR(CR.DNIS_CD,1,3) = MRG.DNIS_CD
AND CR.PRODUCT_CUST_ID = MRG.PRODUCT_CUST_ID
AND ROWNUM = 1
)
WHEN MATCHED THEN UPDATE SET
CR.ISUPDATED = 'Y',
CR.AMOUNT = CASE WHEN MRG.AMOUNT_USD=0 THEN CR.AMOUNT ELSE MRG.AMOUNT_USD END
Update
ROWNUM in the ON clause works on the updated table, not the data in the USING clause. The example below starts with two identical rows and only one gets updated:
create table test1(a number, b number);
insert into test1 values(1, 1);
insert into test1 values(1, 1);
merge into test1
using
(
select 1 a from dual
) test2
on (test1.a = test2.a and rownum = 1)
when matched then update set b = 0;
select * from test1;
A B
- -
1 0
1 1
Oracle 11g: Consider the following two CASE Statements
SEARCHED CASE
with null_table as (select null as null_set from dual )
select
case
when (null_set is null) then 'NULL INDEED'
else 'NOTNULL?'
end as AM_I_NULL_OR_NOT
from null_table
SIMPLE CASE
with null_table as (select null as null_set from dual )
select
case null_set
when (null) then 'NULL INDEED'
else 'NOTNULL?'
end as AM_I_NULL_OR_NOT
from null_table
The Searched CASE evaluates null_set as expected, yet, Simple CASE appears not to do so.
Questions:
How do I perform a Simple CASE evaluation on null_set ?
Why does the Simple CASE evaluate as it does?
In Oracle, null cannot be compared against using the = operator.
For example:
select * from dual where null = null; -- No result
select * from dual where 1 = 1; -- gives a result
So what you can do is use NVL to replace null by another value :
with null_table as (select null as null_set from dual )
select
case nvl(null_set,'X')
when 'X' then 'NULL INDEED'
else 'NOTNULL?'
end as AM_I_NULL_OR_NOT
from null_table
(make sure your field can never be equal to the value, X in the example.)