选择按值计数

时间:2016-08-23 13:23:27

标签: sql oracle

给定一个包含以下字段的表messages

id          | Number
customer_id | Number
source      | VARCHAR2
...

我想知道每个客户有多少条消息,但我想区分source等于'xml'的消息和所有其他来源。

到目前为止我的查询

SELECT customer_id,
  case when source = 'xml' then 'xml' else 'manual' end as xml,
  count(*)
FROM MESSAGES
GROUP BY customer_id, 
  case when source = 'xml' then 'xml' else 'manual' end;

给我一​​个类似的结果:

customer_id | xml    | count
----------------------------
1           | xml    |    12
1           | manual |    34
2           | xml    |    54
3           | xml    |    77
3           | manual |     1
...

这在两个方面相当丑陋:

  1. 我必须在字段列表和组列表中重复case语句
  2. 我现在每个客户有两行。
  3. 问:是否可以制定查询,以便结果看起来像这样?

    customer_id | xml | manual
    --------------------------
    1           |  12 |     34
    2           |  54 |      0
    3           |  11 |      1
    

5 个答案:

答案 0 :(得分:4)

您正在寻找条件聚合:

SELECT customer_id,
       count(case when source = 'xml' then 1 end) as xml_count, 
       count(case when source <> 'xm' then 1 end) as manual_count
FROM MESSAGES
GROUP BY customer_id

这是有效的,因为聚合忽略NULL值,如果CASE不包含案例条件中的值,NULL的结果将为source

答案 1 :(得分:3)

使用条件聚合。

SELECT customer_id,
  sum(case when source = 'xml' then 1 else 0 end) as xml,
  sum(case when source <> 'xml' then 1 else 0 end) as manual
FROM MESSAGES
GROUP BY customer_id

这假定source列不是null。如果在null表达式中coalesce可以使用nvlcase,那么比较会为您提供预期结果。

答案 2 :(得分:1)

这样可行,看起来你没有一个名为'manual'的来源。 COUNT或SUM会给你相同的差异。

SELECT
    customer_id
    ,ISNULL(COUNT(CASE WHEN source = 'xml' THEN 1 END),0) xml
    ,ISNULL(COUNT(CASE WHEN source <> 'xml' OR source IS NULL THEN 1 END),0) manual
FROM Messages
GROUP BY customer_id

这将允许零出现在您通常会看到NULL值的位置,您的样本为零而不是null。

答案 3 :(得分:0)

使用Oracle 11.1中引入的PIVOT操作,这是一个奇特的解决方案(它几乎与vkp的解决方案完全相同)。注意如何在子查询中处理'xml'和所有其他(包括NULL)之间的区别。

select *
from (select customer_id, case when source = 'xml' then 'xml' else 'other' as source
      from messages)
pivot (count(*) for source in ('xml' as xml, 'other' as other))
;

答案 4 :(得分:0)

除了CASE之外,使用解码功能还有其他方法:

 SELECT cust_id,
  COUNT(DECODE(source,'xml','xml'))"XML",
  COUNT(DECODE(source,'manual','manual'))"manual"
FROM MESSAGES
GROUP BY cust_id;

但是,当您将null作为源时,这将不会显示结果。