如何计算“分组依据”组中的行数符合特定条件

时间:2016-03-10 21:07:11

标签: sql postgresql count group-by

我有一个表,我希望通过使用某个键对数据进行分组来选择数据。对于每个组,我还想计算属于该组的行数符合某个标准。即使该组中的0行符合条件,我仍然希望返回该组并显示“计数”字段显示0行符合条件。因此,我不能简单地使用“where”子句过滤掉不需要的行,只需选择组内元素数量的计数。

非常感谢任何帮助

3 个答案:

答案 0 :(得分:4)

我建议使用CASE WHEN(标准ISO SQL语法),如下例所示:

SELECT   a.category,
         SUM(CASE WHEN a.is_interesting = 1 THEN 1 END) AS conditional_count,
         COUNT(*) group_count
FROM     a
GROUP BY a.category

这将总结1和空值的值(当条件为假时),这将归结为实际计算满足条件的记录。

但是当没有记录满足条件时,这将返回 null 。如果你想在这种情况下为0,你可以像这样包装SUM

COALESCE(SUM(CASE WHEN a.is_interesting = 1 THEN 1 END), 0)

或更短,请使用COUNT代替SUM

COUNT(CASE WHEN a.is_interesting = 1 THEN 1 END)

对于COUNT,只要它不是 null ,您在THEN子句中放入的值无关紧要。它将计算表达式不是 null 的实例。

添加ELSE 0子句通常也会返回0 SUM

SUM(CASE WHEN a.is_interesting = 1 THEN 1 ELSE 0 END)

但是有一个边界情况,SUM仍会返回 null 。这是没有GROUP BY子句且没有记录符合WHERE子句的情况。例如:

SELECT SUM(CASE WHEN 1 = 1 THEN 1 ELSE 0 END)
FROM   a
WHERE  1 = 0

将返回 null ,而COUNTCOALESCE版本仍会返回0.

答案 1 :(得分:1)

您有条件GROUP BY。只需添加一个带有可以求和的条件表达式的列:

..., SUM(
   CASE WHEN othercondition THEN 1
        ELSE 0 END
) AS MatchingCondition, ...

条件为true的行将产生1,从而在分组结果中显示为行计数。如果没有行匹配,您将获得NULL,因此您需要将SUM包装在COALESCE中以将其减少到所需的值0。

衍生技巧

这提供了一种针对不同条件进行分组的方法。假设您有三个互斥的不同条件,并且您想要计算所有三个(即,在GROUP BY元组中,您有32行,其中10个匹配条件1,6匹配条件2和16匹配条件3)。如果您还知道组中的最大元组数永远不会超过N,则可以将这三个条件编码为一个数字:

..., SUM(
   CASE WHEN condition1 THEN 1
        WHEN condition2 THEN N
        WHEN condition3 THEN N*N
        WHEN condition4 THEN N*N*N
        ELSE 0 END
) AS MatchingCondition, ...

结果数模N将产生与condition1匹配的行数。数字除以N,模N将产生条件2的匹配。 N * N的模数余数将产生条件3的匹配,依此类推:

num1 = result % N
result = (result - num1) / N
num2 = result % N
result = (result - num2) / N
num3 = result % N
...

(使用更大乘数的进一步细化允许在单个列中编码几个非互斥条件的结果。)

答案 2 :(得分:0)

我认为你需要两张桌子。一个标识您想要计算的类别/组,另一个标识您计算的数据表。然后你可以:

Select Category.Name, 
    (Select Count(*) 
       from mydatatable 
      where mydatatable.CategoryId = Category.CateogryId) as Count

这也会给你零数。