SQL |如何对 3 个项目的分区组求和?

Posted

技术标签:

【中文标题】SQL |如何对 3 个项目的分区组求和?【英文标题】:SQL | How to sum over partition group of 3 items? 【发布时间】:2021-07-23 09:26:08 【问题描述】:

我试图获取前 3 种产品类别的一天收入百分比,但在这个百分比上遇到了困难。我已经将每个产品的收入排在第 1 到第 3 位,但不知道如何获得该百分比。

任何指针将不胜感激。

SELECT * FROM (
SELECT   date, 
         category_name,
         revenue,
         row_number() OVER(PARTITION BY DATE(date) ORDER BY revenue DESC) AS category_rank,
         (revenue / (select sum(revenue) from a group by 1)) * 100 percentage AS percentage_of_daily_total -- this is the wrong one 

  FROM (
    SELECT DATE(orders.order_timestamp) AS date,
           products.product_cat AS category_name,
           ROUND(SUM(payments.payment)) AS revenue
    FROM table1.orders orders
    JOIN table1.t_payments payments ON orders.order_id = payments.order_id
    JOIN table1.t_items items ON orders.order_id = items.order_id
    JOIN table1.t_products products ON items.product_id = products.product_id
    GROUP BY 1 ,2) a) b
WHERE category_rank <= 3;

示例数据如下:日期、类别名称、收入、类别排名

2016-10-05  jeans       20  1
2016-10-05  shirts      15  2
2016-10-05  shoes       10  3
2016-10-06  skirts      50  1
2016-10-06  sports_wear 30  2
2016-10-06  accesories  10  3

期望的结果:日期、类别名称、收入、类别排名、百分比_每日总和

2016-10-05  jeans       30  1  50
2016-10-05  shirts      20  2  33
2016-10-05  shoes       10  3  17
2016-10-06  skirts      20  1  50 
2016-10-06  sports_wear 16  2  40
2016-10-06  accessories 4   3  10

【问题讨论】:

【参考方案1】:

使用CTEs

WITH a AS (
    SELECT DATE(orders.order_timestamp) AS date,
           products.product_cat AS category_name,
           ROUND(SUM(payments.payment)) AS revenue
    FROM table1.orders orders
    JOIN table1.t_payments payments ON orders.order_id = payments.order_id
    JOIN table1.t_items items ON orders.order_id = items.order_id
    JOIN table1.t_products products ON items.product_id = products.product_id
    GROUP BY 1 ,2
)

SELECT * FROM (
SELECT   a.date, 
         a.category_name,
         a.revenue,
         row_number() OVER(PARTITION BY DATE(a.date) ORDER BY a.revenue DESC) AS category_rank,
         (a.revenue / b.revenue_sum) * 100 percentage AS percentage_of_daily_total
  FROM a
  JOIN (SELECT date, sum(revenue) AS revenue_sum FROM a GROUP BY 1) AS b
  ON a.date = b.date)
WHERE category_rank <= 3;

【讨论】:

当您发表评论时,我正在探索 CTA,非常感谢。【参考方案2】:

您的原始查询非常接近。计算 OUTERMOST sql 中的百分比。所以放下你的百分比计算,然后在外部选择:

Select *, 100*revenue/(sum(revenue) Over (Partition by Date)) as percentage_of_daily_total

请记住,当您开始计算窗口函数时,Where 子句已经执行,您每天的记录减少到 3 条,因此任何总数都将仅基于前 3 条。

【讨论】:

以上是关于SQL |如何对 3 个项目的分区组求和?的主要内容,如果未能解决你的问题,请参考以下文章

如何对sql查询引用组中的多列求和

如何在 SQL 中获得对重复项求和的最佳项目?

如何使用 AWS 快速对 100 亿行 SQL 表进行分区?

Oracle SQL:如何对每行的每 x 个后续行求和

如何在 sql 的循环中对函数求和?

Oracle SQL - 对 ID 求和分区但排除重复