Oracle case inside where clause - sql

This is a simple question, I've read some details about using CASE in WHERE clause, but couldn't able to make a clear idea how to use it. The below is my sample query:
1 SELECT * FROM dual
2 WHERE (1 =1)
3 AND (SYSDATE+1 > SYSDATE)
4 AND (30 > 40)
5 AND (25 < 35);
I have a procedure i_value as in parameter.
I need to ignore the 4th line if i_value is 'S' and I need to ignore the 5th line if i_value is 'T'.
Thanks in advance.

I think this is the best way to solve your problem:
select *
from dual
where (1 = 1)
and (sysdate + 1 > sysdate)
and case
when i_value = 'S'
then
case
when (25 < 35)
then 1
else 0
end
when i_value = 'T'
then
case
when (30 > 40)
then 1
else 0
end
end = 1;
Of course, you could use Dynamic SQL, but it'd be more difficult and less effective.

Why so ser use case?
SELECT * FROM dual
WHERE (1 =1)
AND ( SYSDATE+1 > SYSDATE )
AND ( ((30 > 40) and i_value <> 'S') or i_value = 'S' )
AND ( ((25 < 35) and i_value <> 'T') or i_value = 'T' );

SELECT * FROM dual
WHERE (1 =1)
AND (SYSDATE+1 > SYSDATE)
AND CASE WHEN i_value = 'S' THEN 1 ELSE CASE WHEN (30 > 40) THEN 1 ELSE 0 END END = 1
AND CASE WHEN i_value = 'T' THEN 1 ELSE CASE WHEN (25 < 35) THEN 1 ELSE 0 END END = 1;

This should work as well.
case
when (i_value = 'S' and (WHERE (1=1) AND (SYSDATE+1 > SYSDATE) AND (25 < 35)) ) then 1
when (i_value = 'T' and (WHERE (1=1) AND (SYSDATE+1 > SYSDATE) AND (30 < 40)) ) then 1
else 0
end = 1

Related

How PostgreSQL function will return a table format with either select case1 or case2 based on input?

I am trying to do something like this. What is the right way to do it
CREATE OR REPLACE function func(age bigint)
RETURNS TABLE(years int, category text) AS $$
SELECT CASE
WHEN age > 30 THEN SELECT
CASE
WHEN (age >= 60) THEN 0
WHEN (age >= 50) THEN 10
WHEN (age >= 40) THEN 20
ELSE 30
END,
CASE
WHEN (age >= 60) THEN "BABY BOOMER"
WHEN (age >= 40) THEN "BOOMER"
WHEN (age >= 40) THEN "NOOBER"
ELSE "LONER"
END,
WHEN age < 30 THEN SELECT
CASE
WHEN (age >= 20) THEN 20
WHEN (age >= 10) THEN 10
ELSE 0
END,
CASE
WHEN (age >= 20) THEN "MILLENIAL"
WHEN (age >= 10) THEN "GEN X"
ELSE "CERELAX"
END
END
$$
language sql stable strict;
The function should return data in the form of a table but what I need is based on input the returning set of values to be chosen. Basically I need to add conditional return
First a couple concepts need to be cleared up. In Postgres:
double quotes indicate identifiers. Therefore in your query the double quoted "values" are undefined identifiers. String/Text values are indicated by tick marks (single quotes).
A case expression can only return a single result. Thus your form case when x then (case ... end, case ... end) end is invalid as the then would be returning 2 values. While a case expression can return only a single result that result may be a tuple. IE case when ... then (a,b) end is valid.
Further as is your returns null if age = 30. That is kept.
create or replace function func(age bigint)
returns table(years int, category text)
language sql stable strict
as $$
select case
when age >= 60 then ( 0,'BABY BOOMER'::text)
when age >= 50 then (10,'BOOMER'::text)
when age >= 40 then (20,'BOOMER'::text)
when age > 30 then (30,'LONER'::text) -- << ???
when age = 30 then (null::int, null::text) -- ??? >>>
when age >= 20 then (20,'MILLENIAL'::text)
when age >= 10 then (10,'GEN X'::text)
else (0, 'CERELAX'::text)
end ;
$$;
See demo

sql if statement not working

I can't get this if statement to work.
I'm trying to say 'if(number of dates) is greater than 330, return 'x', otherwise give me the (number of dates)
SELECT if(ROUND(COUNT(ClosedDate) / 10, 0) * 10 > 330 then 'X' else ROUND(COUNT(ClosedDate) / 10, 0) * 10) end AS [Previous Day Sales]
FROM PartsSales
WHERE (MONTH(ClosedDate) = MONTH(GETDATE()))
AND (YEAR(ClosedDate) = YEAR(GETDATE()))
AND (DAY(ClosedDate) = DAY(GETDATE() - 13))
Use a CASE clause:
SELECT CASE WHEN ROUND(COUNT(ClosedDate) / 10, 0) * 10 > 330 then 'X' else ROUND(COUNT(ClosedDate) / 10, 0) * 10 end AS [Previous Day Sales]
FROM PartsSales
WHERE (MONTH(ClosedDate) = MONTH(GETDATE())) AND (YEAR(ClosedDate) = YEAR(GETDATE())) AND (DAY(ClosedDate) = DAY(GETDATE() - 13))
Use CASE:
SELECT
CASE WHEN ROUND(COUNT(ClosedDate) / 10, 0) * 10 > 330
THEN 'X' ELSE ROUND(COUNT(ClosedDate) / 10, 0) * 10) END AS [Previous Day Sales]
FROM PartsSales
WHERE MONTH(ClosedDate) = MONTH(GETDATE())
AND YEAR(ClosedDate) = YEAR(GETDATE())
AND DAY(ClosedDate) = DAY(GETDATE() - 13)
I would recommend:
SELECT (CASE WHEN COUNT(*) >= 335 THEN 'X'
ELSE CAST(ROUND(COUNT(ClosedDate) / 10, 0) * 10) as VARCHAR(255))
END) AS [Previous Day Sales]
FROM PartsSales ps
WHERE CAST(ClosedDate as DATE) = CAST(DATEADD(day, -13, GETDATE()) as DATE);
Notes:
You WHERE clause is too complicated.
Why is the "previous day" using the day from 13 days ago?
Be explicit about the types! You are mixing strings and numbers. The result of the case expression needs to be a string.

Getting an error day of month must be between 1 and last day of month

HiAll,
i am getting an error
ORA-01847: day of month must be between 1 and last day of month
01847. 00000 - "day of month must be between 1 and last day of month"
please suggest on this, below is sample i used in my query
when ((
(( x.DailyKMUsage * (trunc(x.std)-trunc(x.ced)) ))
/ case when x.ckm <= 0 then 1 else x.ckm end
)*100 ) > 0
then (((
(( x.DailyKMUsage * (trunc(x.std)-trunc(x.ced)) ))
/ case when x.ckm <= 0 then 1 else x.ckm end
)*100 )|| '% Over Utilised')
when ((
(( x.DailyKMUsage * (trunc(x.std)-trunc(x.ced)) ))
/ case when x.ckm <= 0 then 1 else x.ckm end
)*100 ) < 0
then (((
(( x.DailyKMUsage * (trunc(x.std)-trunc(x.ced)) ))
/ case when x.ckm <= 0 then 1 else x.ckm end
)*100 )|| '% Under Utilised')

Calculate business days between two dates

I tried the following query I got from an earlier question:
SELECT OrderNumber, InstallDate, CompleteDate,
(TRUNC(CompleteDate) - TRUNC(InstallDate) ) +1 -
((((TRUNC(CompleteDate,'D'))-(TRUNC(InstallDate,'D')))/7)*2) -
(CASE WHEN TO_CHAR(InstallDate,'DY','nls_date_language=english')='SUN' THEN 1 ELSE 0 END) -
(CASE WHEN TO_CHAR(CompleteDate,'DY','nls_date_language=english')='SAT' THEN 1 ELSE 0 END) as BusinessDays
FROM Orders
ORDER BY OrderNumber;
But I get an 'ORA-01722 - Invalid Number' error.
What am I doing wrong?
Following is my modified code that I'm having issues with:
select
CASE WHEN a.reqdt=0 THEN to_char('01/01/2010') ELSE TO_CHAR(TO_DATE('01-01-1970','DD-MM-YY') + ( a.reqdt/ 86400000 ), 'MM/DD/YYYY') END AS DT_SENT_TO_VENDOR,
CASE WHEN a.completedt=0 THEN to_char('01/01/2010') ELSE TO_CHAR(TO_DATE('01-01-1970','DD-MM-YY') + ( a.completedt/ 86400000 ), 'MM/DD/YYYY') END AS COMPLETED_DT,
(CASE WHEN a.completedt=0 THEN to_char('01/01/2010') ELSE TO_CHAR(TO_DATE('01-01-1970','DD-MM-YY') + ( a.completedt/ 86400000 ), 'dd-mm-yyyyY') END -
CASE WHEN a.reqdt=0 THEN to_char('01/01/2010') ELSE TO_CHAR(TO_DATE('01-01-1970','DD-MM-YY') + ( a.reqdt/ 86400000 ), 'MM/DD/YYYY') END ) + 1 -
/*(a.completedt - a.reqdt ) + 1 - */
((((TRUNC(a.completedt,'D'))) - (TRUNC(a.reqdt,'D'))/7)*2) -
(CASE WHEN TO_CHAR(a.reqdt,'DY','nls_date_language=american')='SUN' THEN 1 ELSE 0 END) -
(CASE WHEN TO_CHAR(a.completedt,'DY','nls_date_language=american')='SAT' THEN 1 ELSE 0 END) as BusinessDays
from EST_VER a;

Oracle: how to write a query with enable / disable WHERE condition

I've thougth this way to implement a parametrizable query.
Do you know any variant?
WITH temp AS (SELECT 'case1' case FROM DUAL)
SELECT 1
FROM temp
WHERE ( (1 = DECODE (case, 'case1', 1, 0))
AND SYSDATE > TO_DATE ('01/01/2013', 'DD/MM/YYYY'))
OR ( (1 = DECODE (case, 'case2', 1, 0))
AND SYSDATE < TO_DATE ('01/01/2013', 'DD/MM/YYYY'))
you can use case
WITH temp AS (SELECT 'case1' _case FROM DUAL)
SELECT 1
FROM temp
WHERE
1 = case
when _case = 'case1'
AND SYSDATE > TO_DATE ('01/01/2013', 'DD/MM/YYYY')
then 1
when _case = 'case2'
AND SYSDATE > TO_DATE ('01/01/2013', 'DD/MM/YYYY')
then 1
else 0
end
;
This seems awkward. You can do this with just basic logic:
WITH temp AS (SELECT 'case1' case FROM DUAL)
SELECT 1
FROM temp
WHERE ((case = 'case1') and SYSDATE > TO_DATE('01/01/2013', 'DD/MM/YYYY')) or
((case = 'case2') and SYSDATE < TO_DATE('01/01/2013', 'DD/MM/YYYY'))
Why not use a function:
CREATE FUNCTION x ( p_case IN VARCHAR2, p_date IN VARCHAR2 )
RETURN INTEGER
IS
BEGIN
IF p_case = 'case1' AND TO_DATE(p_date, 'DD/MM/YYYY') < SYSDATE THEN RETURN 1;
ELSE IF p_case = 'case2' AND TO_DATE(p_date, 'DD/MM/YYYY') < SYSDATE THEN RETURN 1;
ELSE RETURN 0;
END IF;
END;
SELECT 1 FROM dual WHERE x('case1', '01/01/2013') = 1;