Question

I get a "missing keyword" error for the following simple code: How can I get a result 3 , 4, and 5 if i_check = 'Y' AND only 4 and 5 if i_check = 'N'

WITH t(val) AS
     ( SELECT 1 FROM dual
     UNION ALL
     SELECT 2 FROM dual
     UNION ALL
     SELECT 3 FROM dual
     UNION ALL
     SELECT 4 FROM dual
     UNION ALL
     SELECT 5 FROM dual
     )
SELECT *
FROM t
WHERE CASE WHEN i_check  = 'Y' THEN VAL >= 3
           WHEN i_check  = 'N' THEN VAL  > 3
      END;

Editing with a clear data:

 WITH t(val) AS
     ( SELECT trunc(sysdate) FROM dual
     UNION ALL
     SELECT trunc(sysdate) + interval '10' minute FROM dual
     UNION ALL
     SELECT trunc(sysdate) + interval '1' hour FROM dual
     UNION ALL
     SELECT trunc(sysdate) + interval '2' hour + interval '1' second FROM dual
     UNION ALL
     SELECT trunc(sysdate) + 1 FROM dual
     )
SELECT *
FROM t

19/02/2014 12:00:00 AM
19/02/2014 12:10:00 AM
19/02/2014 01:00:00 AM
19/02/2014 02:00:01 AM
20/02/2014 12:00:00 AM

The inputs are i_check and i_date

if i_check = 'Y' AND i_date =19/02/2014 01:00:00 AM'` then

19/02/2014 01:00:00 AM, 19/02/2014 02:00:01 AM, 20/02/2014 12:00:00 AM 

if i_check = 'N' AND i_date =19/02/2014 01:00:00 AM'` then

19/02/2014 02:00:01 AM, 20/02/2014 12:00:00 AM 

Thanks for any help in advance:)

Was it helpful?

Solution 2

CASE WHEN must return a value, not a statement. Why just not user simple logical AND/OR statements? :) For example, the first query can be rewritten like this:

WITH t(val) AS
     ( SELECT 1 FROM dual
     UNION ALL
     SELECT 2 FROM dual
     UNION ALL
     SELECT 3 FROM dual
     UNION ALL
     SELECT 4 FROM dual
     UNION ALL
     SELECT 5 FROM dual
     )
SELECT *
FROM t
WHERE (i_check  = 'Y' AND VAL >= 3)
      OR (i_check  = 'N' AND VAL > 3);

As for the second query, it should be something like this:

WITH t(val) AS
     ( SELECT trunc(sysdate) FROM dual
     UNION ALL
     SELECT trunc(sysdate) + interval '10' minute FROM dual
     UNION ALL
     SELECT trunc(sysdate) + interval '1' hour FROM dual
     UNION ALL
     SELECT trunc(sysdate) + interval '2' hour + interval '1' second FROM dual
     UNION ALL
     SELECT trunc(sysdate) + 1 FROM dual
     )
SELECT *
FROM t
WHERE (:i_check = 'Y' AND VAL >= :i_date)
      OR (:i_check = 'N' AND VAL > :i_date)

OTHER TIPS

You cannot return a boolean condition to a where clause, instead use case like this way

 WITH t(val) AS
     ( SELECT 1 FROM dual
     UNION ALL
     SELECT 2 FROM dual
     UNION ALL
     SELECT 3 FROM dual
     UNION ALL
     SELECT 4 FROM dual
     UNION ALL
     SELECT 5 FROM dual
     )
SELECT *
FROM t
WHERE val > (CASE WHEN i_check  = 'Y' THEN  2
                  WHEN i_check  = 'N' THEN  3
              END);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top