【问题标题】:Why do you need to include a field in GROUP BY when using OVER (PARTITION BY x)?为什么在使用 OVER (PARTITION BY x) 时需要在 GROUP BY 中包含字段?
【发布时间】:2018-03-18 16:00:11
【问题描述】:

我有一个表,我想对一个字段进行简单的求和,按两列分组。然后我想要每个 year_num 的所有值的总数。

参见示例:http://rextester.com/QSLRS68794

此查询抛出:“42803:列“foo.num_cust”必须出现在 GROUP BY 子句中或用于聚合函数中”,我不知道为什么。 为什么使用 OVER (PARTITION BY x) 的聚合函数需要求和字段在 GROUP BY 中??

select 
    year_num
    ,age_bucket
    ,sum(num_cust)
    --,sum(num_cust) over (partition by year_num)  --THROWS ERROR!!
from
    foo
group by
    year_num
    ,age_bucket
order by 1,2

表格:

| loc_id |  year_num |  gen |  cust_category |  cust_age |  num_cust |  age_bucket |
|--------|-----------|------|----------------|-----------|-----------|-------------|
| 1      | 2016      | M    | cash           | 41        | 2         | 04_<45      |
| 1      | 2016      | F    | Prepaid        | 41        | 1         | 03_<35      |
| 1      | 2016      | F    | cc             | 61        | 1         | 05_45+      |
| 1      | 2016      | F    | cc             | 19        | 2         | 02_<25      |
| 1      | 2016      | M    | cc             | 64        | 1         | 05_45+      |
| 1      | 2016      | F    | cash           | 46        | 1         | 05_45+      |
| 1      | 2016      | F    | cash           | 27        | 3         | 03_<35      |
| 1      | 2016      | M    | cash           | 42        | 1         | 04_<45      |
| 1      | 2017      | F    | cc             | 35        | 1         | 04_<45      |
| 1      | 2017      | F    | cc             | 37        | 1         | 04_<45      |
| 1      | 2017      | F    | cash           | 46        | 1         | 05_45+      |
| 1      | 2016      | F    | cash           | 19        | 4         | 02_<25      |
| 1      | 2017      | M    | cash           | 43        | 1         | 04_<45      |
| 1      | 2017      | M    | cash           | 29        | 1         | 03_<35      |
| 1      | 2016      | F    | cc             | 13        | 1         | 01_<18      |
| 1      | 2017      | F    | cash           | 16        | 2         | 01_<18      |
| 1      | 2016      | F    | cc             | 17        | 2         | 01_<18      |
| 1      | 2016      | M    | cc             | 17        | 2         | 01_<18      |
| 1      | 2017      | F    | cash           | 18        | 9         | 02_<25      |

期望的输出:

| year_num | age_bucket | sum | sum over (year_num) |
|----------|------------|-----|---------------------|
| 2016     | 01_<18     | 5   | 21                  |
| 2016     | 02_<25     | 6   | 21                  |
| 2016     | 03_<35     | 4   | 21                  |
| 2016     | 04_<45     | 3   | 21                  |
| 2016     | 05_45+     | 3   | 21                  |
| 2017     | 01_<18     | 2   | 16                  |
| 2017     | 02_<25     | 9   | 16                  |
| 2017     | 03_<35     | 1   | 16                  |
| 2017     | 04_<45     | 3   | 16                  |
| 2017     | 05_45+     | 1   | 16                  |

【问题讨论】:

    标签: sql postgresql aggregate-functions window-functions


    【解决方案1】:

    你需要嵌套sum()s:

    select year_num, age_bucket, sum(num_cust),
           sum(sum(num_cust)) over (partition by year_num)  --WORKS!!
    from foo
    group by year_num, age_bucket
    order by 1, 2;
    

    为什么?好吧,窗口函数没有进行聚合。参数必须是一个可以在group by 之后计算的表达式(因为这是一个聚合查询)。因为num_cust 不是group by 键,所以它需要一个聚合函数。

    如果您使用子查询,这可能会更清楚:

    select year_num, age_bucket, sum_num_cust,
           sum(sum_num_cust) over (partition by year_num)
    from (select year_num, age_bucket, sum(num_cust) as sum_num_cust
          from foo
          group by year_num, age_bucket
         ) ya
    order by 1, 2;
    

    这两个查询的作用完全相同。但是使用子查询应该更清楚为什么需要额外的聚合。

    【讨论】:

    • @Gordon Linoff,您能解释一下窗口函数sum() over () 与常规sum() 聚合fxn 有何不同吗?在此示例中,num_cust 不包含在 group by 子句中,那么为什么它适用于 sum() 而不适用于 sum() over (partition by)?我不是专家,所以如果你能在解释器如何处理带有和不带有窗口函数的GROUP BY 的上下文中解释这一点,那将会很有帮助。
    • @Gordon 你能解释一下窗函数 sum() over () 与常规 sum() 聚合 fxn 有何不同吗?在这个例子中,num_cust 没有包含在 group by 子句中,那么为什么它对 sum() 有效,但对 sum() over (partition by) 无效?我不是专家,所以如果你能在解释器如何处理带有和不带有窗口函数的 GROUP BY 的上下文中解释这一点,那将会很有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多