20

I have an SQL-query where I use Oracle CASE to compare if a date column is less than or greater than current date. But how do I use that CASE-statement in a GROUP BY-statement? I would like to count the records in each case.

E.g.

select
    (case
        when exp_date > sysdate then 1
        when exp_date <= sysdate then 2
        else 3
     end) expired, count(*)
from mytable
group by expired

But I get an error when trying this: ORA-00904. Any suggestions?

Jonas
  • 121,568
  • 97
  • 310
  • 388

3 Answers3

28
select
(case
    when exp_date > sysdate then 1
    when exp_date <= sysdate then 2
    else 3
 end) expired, count(*)
from mytable
group by (case
    when exp_date > sysdate then 1
    when exp_date <= sysdate then 2
    else 3
 end)
paul
  • 21,653
  • 1
  • 53
  • 54
  • what the difference with the in-line view in terms of performances ? – Donatello Sep 08 '14 at 13:22
  • 1
    I'm not sure. Would depend on whether oracle evaluates the `CASE` twice. You could check using `EXPLAIN PLAN`. In any case, with hindsight, I'd probably go with @Ollie answer, as I think the SQL looks better without the duplicated logic – paul Sep 08 '14 at 13:37
  • What if I want 1,2,3 as column Header, how should I write the sql? – Kshitij Manvelikar Jan 17 '20 at 04:05
27

Use an inline view:

SELECT expired,
       count(*)
  FROM (SELECT (CASE
                   WHEN exp_date > SYSDATE THEN 1
                   WHEN exp_date <= SYSDATE THEN 2
                   ELSE 3
                 END) AS expired
          FROM mytable)
GROUP BY expired;

Hope it helps...

Ollie
  • 17,058
  • 7
  • 48
  • 59
2

As an additional input, although it does not relate to this thread, you can also aggregate your case statements without mentioning it in the group by clause.

SELECT
   WORK_ORDER_NUMBER,
   SUM(CASE WHEN STOCK_CODE LIKE 'xxxx' THEN STOCK_QUANTITY ELSE 0 END) AS TOTAL
FROM Table
GROUP BY WORK_ORDER_NUMBER;
ZygD
  • 22,092
  • 39
  • 79
  • 102
JayKayOf4
  • 1,202
  • 1
  • 12
  • 15