【问题标题】:PostgreSQL - Conditional aggregation - Avg() in Select statementPostgreSQL - 条件聚合 - Select 语句中的 Avg()
【发布时间】:2013-06-17 08:01:28
【问题描述】:

我有这张桌子

| user         | Mark       | Points   |
|--------------|------------|----------|
| John         |    0       |    2     |
| Paul         |    5       |    3     |
| John         |    4       |    4     |
| Paul         |    7       |    5     |

我想用一个返回如下所示行的 select 语句构建一个查询。 Avg(Mark) - 只有在 Mark>0 时才应该是平均值 Sum(Points) - 应该是所有记录的总和。

| user         | Avg(Mark)  | Sum(Points) |
|--------------|------------|-------------|
| John         |    4       |    6        |
| Paul         |    6       |    8        |

谁能指出正确的语法?

我相信它应该喜欢:

select user, avg(Mark>0), sum(Points) from Table group by user;

【问题讨论】:

    标签: postgresql select aggregate-functions


    【解决方案1】:
    select
        user, -- very bad choice for column name, but i assume it's just SO example, not real column
        sum( mark ) / count (nullif(mark, 0))
    from
        table
    group by
        user
    

    应该是这样的伎俩。

    【讨论】:

    • 如果 'John' 的所有 'Marks' 值为零,是否还有可能避免除以零?
    • 我想我已经解决了 sum(mark) / nullif(count (nullif(mark, 0)),0) 再次感谢您的帮助。
    【解决方案2】:

    怎么样:

    select user,
           avg(case when mark > 0 then mark end),
           sum(mark)
    from   ...
    

    【讨论】:

      【解决方案3】:

      从 9.4 版本开始,PostgreSQL 直接支持过滤聚合。

      https://www.postgresql.org/docs/9.4/static/sql-expressions.html

      如果指定了 FILTER,则只有 filter_clause 计算结果为 true 的输入行被馈送到聚合函数;其他行被丢弃。

      通过使用它,你的例子可以改写为:

      SELECT
          "user",
          AVG(mark) FILTER (WHERE mark > 0),
          SUM(points)
      FROM
          "table"
      GROUP BY
          "user"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-07
        • 1970-01-01
        • 2021-02-16
        • 2014-04-05
        • 1970-01-01
        • 2022-01-05
        • 2012-10-03
        • 1970-01-01
        相关资源
        最近更新 更多