【问题标题】:Use Count function inside conditional part of Case Expression在 Case Expression 的条件部分使用 Count 函数
【发布时间】:2017-12-12 11:31:36
【问题描述】:

我在 oracle 数据库中有两个带有以下示例记录的表

1.员工

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

2。员工账户

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

我想要这样的结果

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

这可以通过外部查询来实现,但是我想写一个没有外部查询的查询。想要在一个查询中完成。

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

上面的查询给出了错误ORA-00907: missing right parenthesis。可以在单个查询中完成还是外部查询是唯一的出路。

Oracle Version is 10g 

【问题讨论】:

  • 案例表达式,不是陈述。 (它返回一个值。)
  • 对于PQR 怎么总是1。应该是2。不是吗?
  • @XING PQR 只有一名员工Samstaffaccounts 表中有单个帐户。所以PQR 在单账户类型中有 1 个,在双账户类型中有 1 个
  • 我认为在预期结果中应该再列出一个ABCDouble Double Single
  • @Susang no as PQR 有 1 名员工单账户和 1 名双账户,ABC 有 2 名双账户员工和 1 名单账户员工。共有5名员工(1(PQR-S)+1(ABC-S)+1(PQR-D)+2(ABC-D))

标签: sql oracle count aggregate-functions case-when


【解决方案1】:

也许这样的事情会起作用。

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;  

【讨论】:

  • @SangeetMenon :您能解释一下PQR DOUBLE 1 这行应该如何出现在您的结果中吗?否则,查询似乎工作正常。
  • staffsPQR Jack 5 中,Jack 在staffaccounts 中有两个帐户,这就是为什么PQR DOUBLE 1
【解决方案2】:

您按inst_name 分组,但这不是您真正想要的,因为您不希望每个inst_name 的结果行,而是每个inst_nameaccount_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;

【讨论】:

  • 正如我所说.. 我不想要外部查询。你有两个查询(内部和外部),我想避免这种情况。谢谢
  • 啊,好吧,您不想从派生表中进行选择。不过,您希望聚合而不是聚合。我想你可以用COUNT OVER 加上DISTINCT 来欺骗你,但这只会导致查询变得模糊和变慢。那么你为什么要这样做呢?为什么要写一个更糟糕的查询只是为了遵守一些奇怪的规则?
  • 我现在坚持规则。可以向我询问您实际上如何使用COUNT OVER 加上DISTINCT 来做到这一点
【解决方案3】:

您应该学习如何正确使用JOIN 语法。我更喜欢CASE 的显式比较语法。

这可能是你想要的:

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;

编辑:

现在我明白你想要什么了:

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);

【讨论】:

  • 更改联接不会产生预期的结果。谢谢。您的查询返回的结果与我的相同。
  • @SangeetMenon 。 . .请参阅答案的编辑。我不明白你想做什么。
【解决方案4】:

我得到了只有使用subquery 的方法,但可以通过(more easier and readable) 轻松实现您的要求

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

输出

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

【讨论】:

  • 我知道sub-query 是最好的解决方案,但不幸的是我无法使用它。谢谢
猜你喜欢
  • 2015-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-17
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多