【问题标题】:Conditional SQL count条件 SQL 计数
【发布时间】:2015-05-15 05:12:19
【问题描述】:

创建计算表中数据出现次数的列的最佳方法是什么?表格需要按一列分组吗?
我的数据库是 PostgreSQL。

我见过:

SELECT
    sum(CASE WHEN question1 = 0 THEN 1 ELSE 0 END) AS ZERO,
    sum(CASE WHEN question1 = 1 THEN 1 ELSE 0 END) AS ONE,
    sum(CASE WHEN question1 = 2 THEN 1 ELSE 0 END) AS TWO,
    category
FROM reviews
    GROUP BY category

其中question1 的值可以是012

我还看到了一个使用count(CASE WHEN question1 = 0 THEN 1)的版本

但是,随着question1 的可能值数量的增加,这将变得更加繁琐。有没有一种方便的方法来编写这个查询,可能会优化性能?

【问题讨论】:

  • 您的版本相当合理,但如果您希望它在语法上正确,您应该包含end。另一种方法是 Postgres 的 crosstab 功能。我不知道哪个性能更好。
  • 对不起,忘记输入结尾
  • 为什么不按类别和问题1分组并按组计算行数?
  • @GiorgiNakeuri OP 想要 question1 的每个值的列名,然后您需要将结果转置为所需的结果。
  • @Ram,啊哈,好吧,我知道了。在 MSSQL 中,它将按类别和问题分组,然后旋转分组结果。

标签: sql postgresql count group-by aggregate-filter


【解决方案1】:

在 Postgres 9.4 或更高版本中,使用聚合 FILTER 选项。通常是最干净和最快的:

SELECT category
     , count(*) FILTER (WHERE question1 = 0) AS zero
     , count(*) FILTER (WHERE question1 = 1) AS one
     , count(*) FILTER (WHERE question1 = 2) AS two
FROM   reviews
GROUP  BY 1;

FILTER 子句的详细信息:

如果你想要它

SELECT category
     , count(question1 = 0 OR NULL) AS zero
     , count(question1 = 1 OR NULL) AS one
     , count(question1 = 2 OR NULL) AS two
FROM   reviews
GROUP  BY 1;

更多语法变体:

正确的交叉表查询

crosstab() 产生最佳性能,并且对于长选项列表更短:

SELECT * FROM crosstab(
     'SELECT category, question1, count(*) AS ct
      FROM   reviews
      GROUP  BY 1, 2
      ORDER  BY 1, 2'
   , 'VALUES (0), (1), (2)'
   ) AS ct (category text, zero int, one int, two int);

详细解释:

【讨论】:

    【解决方案2】:

    “最好”的方式(对我而言)是编写如下查询:

    SELECT
        category,
        question1,
        count(*)
    FROM reviews
    GROUP BY category, question1
    

    然后我使用这些数据在应用程序逻辑中绘制一个表格。

    其他选项是对所有分组结果使用一个 JSON 列。这将导致类似:

    category1 | {"zero": 1, "one": 3, "two": 5}
    category2 | {"one": 7, "two": 4}
    

    等等。

    您可以使用json_build_objectjson_agg 从上一个查询中构建此选项的查询。此选项的最佳选择 - 您无需提前知道可能的 question1 值的数量。

    【讨论】:

      猜你喜欢
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-19
      • 1970-01-01
      • 2011-12-19
      • 2014-08-01
      相关资源
      最近更新 更多