简体   繁体   中英

Use Count function inside conditional part of Case Expression

I have two tables with the following sample records in oracle database

1. staffs

inst_name   name    sid
ABC         John    1
PQR         Sam     2
ABC         Tom     3
ABC         Amit    4
PQR         Jack    5

2. staffaccounts

sid     account_no
1       4587
1       4588
2       4589
3       4581
3       4582
5       4583
5       4585
4       4586

Where I want the result like

inst_name   account_type    total
PQR         SINGLE          1
ABC         SINGLE          1
PQR         DOUBLE          1
ABC         DOUBLE          2

This can be achieved by a outer query, but I want to write a query where there is no outer query. Want to accomplish it in one single query.

SELECT
    A .inst_name,
    (
        CASE COUNT (b.ac_no)
        WHEN 1 THEN
            'Single'
        WHEN 2 THEN
            'Double'
        END
    ) account_type,
    COUNT (A . NAME)
FROM
    staffs A,
    staffaccounts b
WHERE
    A . s_id = b.s_id
GROUP BY
    A .inst_name

The above query gives error ORA-00907: missing right parenthesis . Can it be done in single query or is outer query the only way out.

Oracle Version is 10g 

May be something like this would work.

SELECT
    A.inst_name,
        CASE COUNT (b.account_no)
        WHEN 1 THEN
            'Single'
        WHEN 2 THEN
            'Double'
        END account_type,
    COUNT (A.name)
FROM
    staffs A JOIN
    staffaccounts b
ON
    A.SID = b.sid
GROUP BY
    A.inst_name , a.sid
    ORDER BY 3;  

You should learn how to properly use JOIN syntax. I prefer the explicit comparison syntax for CASE .

This may be what you want:

SELECT s.inst_name,
       (CASE WHEN COUNT(sa.ac_no) = 1 THEN 'Single'
             WHEN COUNT(sa.ac_no) = 2 THEN 'Double'
        END) as account_type,
       COUNT(*)
FROM staffs s JOIN
     staffaccounts sa
     ON s.SID = sa.sid
GROUP BY s.inst_name;

EDIT:

Now I see what you want:

SELECT s.inst_name,
       (CASE WHEN cnt = 1 THEN 'Single'
             WHEN cnt = 2 THEN 'Double'
        END) as account_type,
       COUNT(*)
FROM (SELECT s.*, COUNT(*) as cnt
      FROM staffs s JOIN
           staffaccounts sa
           ON s.SID = sa.sid
      GROUP BY s.id
     ) s
GROUP BY s.inst_name,
         (CASE WHEN cnt = 1 THEN 'Single'
               WHEN cnt = 2 THEN 'Double'
          END);

You are grouping by inst_name , but this is not what you actually want, because you don't want a result row per inst_name , but per inst_name and account_type .

select
  s.inst_name,
  sa.account_type,
  count(*) as total
from staffs s
join
(
  select 
    sid, 
    case when count(*) = 1 then 'SINGLE' else 'DOUBLE' end as account_type
  from staffaccounts
  group by sid
  having count(*) <= 2
) sa on sa.sid = s.sid
group by sa.account_type, s.inst_name
order by sa.account_type, s.inst_name;

I got only the way by using subquery but is in the easy way (more easier and readable) to achieve your requirement

SELECT inst_name, account_type, count(total) as total
FROM (
    SELECT
        a.inst_name, 
        CASE 
            WHEN COUNT (b.account_no) = 1 THEN 'Single'
            WHEN COUNT (b.account_no) = 2 THEN 'Double'
        END AS account_type,
        COUNT (a.name) AS total
    FROM staffs a
    INNER JOIN staffaccounts b ON A . SID = b.sid
    GROUP BY a.inst_name, a.sid) t GROUP BY inst_name, account_type

OUTPUT :

inst_name   account_type    total
ABC         Double          2
PQR         Double          1
ABC         Single          1
PQR         Single          1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM