【问题标题】:how to avoid sum(sum()) when writing this postgres query with window functions?使用窗口函数编写此 postgres 查询时如何避免 sum(sum())?
【发布时间】:2020-11-17 03:38:52
【问题描述】:

https://www.db-fiddle.com/f/ssrpQyyajYdZkkkAJBaYUp/0的可运行查询示例

我有一个 postgres 销售表;每行都有一个sale_idproduct_idsalespersonprice

我想为每个至少有一次销售的 (salesperson, product_id) 元组编写一个返回的查询:

  • price 表示该销售人员为该产品所做的所有销售(请致电此product_sales)。
  • price 的总数超过了该销售人员的所有销售额(调用此total_sales)。

我目前的查询如下,但我觉得写sum(sum(price))很傻。有没有更标准/惯用的方法?

select 
  salesperson,
  product_id,
  sum(price) as product_sales,
  sum(sum(price)) over (partition by salesperson) as total_sales
from sales
group by 1, 2
order by 1, 2

写入 sum(price) 而不是 sum(sum(price)) 会产生以下错误:

column "sales.price" must appear in the GROUP BY clause or be used in an aggregate function

更新

  • 请参阅this response 了解使用WITH 子句的好方法。我觉得我应该能够在没有子查询或 WITH 的情况下做到这一点。

  • 刚刚偶然发现this response 提出了另一个问题,该问题提出了sum(sum(...)) 和子查询方法。也许这些是最好的选择?

【问题讨论】:

  • 您的方法是正确的方法。克服你的愚蠢。窗口函数非常强大,这是聚合的正确语法。
  • @GordonLinoff 很公平:-)
  • 。 .我可能有点苛刻。我记得曾经有完全相同的反应。一两天就过去了。

标签: sql postgresql window-functions


【解决方案1】:

您可以使用公用表表达式来简化查询并分两步完成。

例如:

with 
s as (
  select 
    salesperson,
    product_id,
    sum(price) as product_sales
  from sales
  group by salesperson, product_id
)
select
  salesperson, 
  product_id,
  product_sales,
  sum(product_sales) over (partition by salesperson) as total_sales
from s
order by salesperson, product_id

结果:

 salesperson  product_id  product_sales  total_sales 
 ------------ ----------- -------------- ----------- 
 Alice        1           2000           5400        
 Alice        2           2200           5400        
 Alice        3           1200           5400        
 Bobby        1           2000           4300        
 Bobby        2           1100           4300        
 Bobby        3           1200           4300        
 Chuck        1           2000           4300        
 Chuck        2           1100           4300        
 Chuck        3           1200           4300        

请参阅DB Fiddle 的运行示例。

【讨论】:

  • 好点,谢谢!我仍然觉得我应该能够在没有 CTE 或子查询的情况下做到这一点,但你的方法看起来肯定比我的原始代码更合理。
【解决方案2】:

你可以试试下面的-

select * from
(
select 
  salesperson,
  product_id,
  sum(price) over(partition by salesperson,product_id) as product_sales,
  sum(price) over(partition by salesperson) as total_sales,
  row_number() over(partition by salesperson,product_id order by sale_id) as rn
from sales s
)A where rn=1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 2022-01-20
    • 1970-01-01
    • 2017-02-09
    相关资源
    最近更新 更多