0

I have oracle database table 'mytable' with following data-

Sr_NO    Name   Status  Date
121      HP     OK     12/06/2018
122      Dell   OK     15/06/2018
123      MAC    NOK    30/07/2018
124      Apple  NOK    03/09/2018
125      MI     NOK    04/09/2018
126      Oppo   NOK    05/09/2018
127      Vivo   OK     06/09/2018

I want to get output in following format-

Category        Count   OK  NOK
Till 30th Jul   3       2   1
After 30th Jul  4       1   3
Total           7       3   4
1
  • 2
    Just curious - why is the cutoff July 30, and not July 31? Also, shouldn't the Category also show which year that "30th July" is? Commented Sep 29, 2018 at 14:06

2 Answers 2

2

You can use conditional aggregation to get the columns and grouping sets to get the additional row:

select (case when date <= '2018-07-30' then 'Till 30th Jul'
             else 'After 30th Jul'
        end) as category,
       count(*),
       sum(case when status = 'OK' then 1 else 0 end) as OK,
       sum(case when status = 'NOK' then 1 else 0 end) as NOK
from t
group by grouping sets ( ( (case when date <= '2018-07-30' then 'Till 30th Jul'
                                 else 'After 30th Jul'
                             end)
                         ),
                         ()
                        );

You can add total as a category -- in your case -- using a comparison to NULL:

select (case when date is null then 'Total'
             when date <= '2018-07-30' then 'Till 30th Jul'
             else 'After 30th Jul'
        end) as category,

You have no NULL dates in your data, so this is fine. Otherwise you should use GROUPING().

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Gordon, It worked :) I am getting output as following- Category Count OK NOK Till 30th Jul 3 2 1 After 30th Jul 4 1 3 7 3 4
However, I was trying to add the 'Total' as Category for the total count by using
select (case when date <= '2018-07-30' then 'Till 30th Jul' when date > '2018-07-30' then 'After 30th Jul' else 'total' end) as category, count(*) as count, sum(case when status = 'OK' then 1 else 0 end) as OK, sum(case when status = 'NOK' then 1 else 0 end) as NOK from t group by grouping sets ( ( (case when date <= '2018-07-30' then 'Till 30th Jul' when date > '2018-07-30' then 'After 30th Jul' else 'total' end) ), ()); But it's not working
1

Don't use Oracle keywords like DATE and COUNT as column names. I changed those to DT and CT.

This is a simple job for GROUP BY ROLLUP, after you create an additional column FLAG to show which group each row belongs to. I created the flag as 'b' for "before July 30 2018" - otherwise the flag is NULL. (This allows me to use the flag in ORDER BY also, since by default ordering by FLAG is NULLS LAST.)

Remember to remove the WITH clause in its entirety before you run the query, and use your actual table and column names.

alter session set nls_date_format = 'dd/mm/yyyy';

with
  test_data (sr_no, name, status, dt) as (
    select 121, 'HP'   , 'OK' , to_date('12/06/2018') from dual union all
    select 122, 'Dell' , 'OK' , to_date('15/06/2018') from dual union all
    select 123, 'MAC'  , 'NOK', to_date('30/07/2018') from dual union all
    select 124, 'Apple', 'NOK', to_date('03/09/2018') from dual union all
    select 125, 'MI'   , 'NOK', to_date('04/09/2018') from dual union all
    select 126, 'Oppo' , 'NOK', to_date('05/09/2018') from dual union all
    select 127, 'Vivo' , 'OK' , to_date('06/09/2018') from dual
  )
select case grouping_id(flag) when 0
                              then case flag when 'b' then 'Till 30th July'
                                             else          'After 30th July'
                                   end
                              else                         'Total'
       end                                      as category
     , count(status)                            as ct
     , count(case status when 'OK' then 0 end)  as ok
     , count(case status when 'NOK' then 0 end) as nok
from   ( select sr_no, name, status, dt, 
                case when dt <= date '2018-07-30' then 'b' end as flag
         from   test_data
       )
group by rollup(flag)
order by grouping_id(flag), flag
;

CATEGORY                CT         OK        NOK
--------------- ---------- ---------- ----------
Till 30th July           3          2          1
After 30th July          4          1          3
Total                    7          3          4

2 Comments

I wanted to use one more condition for 'nok' to include in 'nok' count where value in 'Status' column is NULL- count(case status when 'NOK' OR is NULL then 0 end) as nok but it's not working.
@PraveenVerma - good idea, bad syntax. The correct syntax (and you must call status by name twice) is count(case when status = 'NOK' or status is NULL then 0 end) as nok.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.