【问题标题】:How to count how many rows inside a "group by" group meets a certain criteria如何计算“分组依据”组中有多少行符合特定条件
【发布时间】:2016-06-25 22:26:17
【问题描述】:

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

任何帮助将不胜感激

【问题讨论】:

标签: sql postgresql count group-by


【解决方案1】:

我建议使用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 和空值(条件为 false 时)的值相加,归结为实际计算满足条件的记录。

然而,当没有记录满足条件时,这将返回 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,您在THEN 子句中输入什么值并不重要,只要它不是null。它将计算表达式不为 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。

【讨论】:

  • 我相信您需要使用这种方法的else 0nullsumnull,我认为 OP 想要显示 0。
  • 在您发表评论时正在编辑我的答案。 ;-)。请注意,使用else 0 您仍然可以获得 null,在极端情况下没有记录。
  • 我不确定你的意思。整个表中没有符合条件的记录,或者组中没有符合条件的记录?因为如果没有记录满足使用 SUM(CASE "condition" THEN 1 ELSE 0 END) 的条件,我会得到该组的 COUNT=0
  • 极端情况是你只有一个组,没有GROUP BYclause,比如SELECT SUM(...) FROM a WHERE ....,并且没有记录满足WHERE条件。
【解决方案2】:

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

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

条件为真的行将产生 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 将产生多少行匹配条件 1。数字除以 N,模 N 将产生条件 2 的匹配项。 N*N 的模余数将产生条件 3 的匹配项,依此类推:

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

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

【讨论】:

  • if 的形式是 MySQL 主义。
  • 这正是我想要的!你为我节省了很多时间,谢谢
  • 实际上,@trincot 的答案是正确的(它考虑了 NULL 的情况)。我有点从臀部射击:-(
【解决方案3】:

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

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

这也会给你零计数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    • 1970-01-01
    相关资源
    最近更新 更多