(Presto)SQL:按列“A”和“B”以及计数列“C”分组,但也包括仅按“A”分组的“C”计数
Posted
技术标签:
【中文标题】(Presto)SQL:按列“A”和“B”以及计数列“C”分组,但也包括仅按“A”分组的“C”计数【英文标题】:(Presto) SQL: Group by on columns "A" and "B" and count column "C", but also include count of "C" grouped only by "A" 【发布时间】:2021-11-24 23:39:38 【问题描述】:这个问题的标题感觉有点奇怪,所以如果你能想象出更好的标题,请随时提供帮助。
你好,
想象一下这样的情况 - 有一个包含 3 列的“Sales”表:date
、store
和 sale_price
,每一行表示单个项目销售:
date | store | sale_price
---------------+---------+------------
2021-09-01 | foo | 15
2021-09-01 | foo | 10
2021-09-01 | foo | 10
2021-09-01 | bar | 5
2021-09-02 | foo | 30
2021-09-02 | bar | 40
2021-09-02 | bar | 20
etc...
我要做的是创建一个按date
和store
分组的查询,并计算每家商店每天售出的商品数量(因此,不考虑价格)。到目前为止,这很容易,但出于可视化目的,我还尝试添加一个额外的行,该行每天还包括销售总数。
这是我正在寻找的最终结果:
date | store | sales_count
---------------+-------------+------------
2021-09-01 | foo | 3
2021-09-01 | bar | 1
2021-09-01 | aggregate | 4
2021-09-02 | foo | 1
2021-09-02 | bar | 2
2021-09-02 | aggregate | 3
etc...
我知道我可以通过 UNION ALL
来创建它,但它不是超级高效,因为它会扫描原始表两次:
SELECT date,
store,
count(sale_price) AS sales_count
FROM sales
GROUP BY 1, 2
UNION ALL
SELECT date,
'aggregate' AS store,
count(sale_price) AS sales_count
FROM sales
GROUP BY 1
我也知道我可以使用over()
子句创建一个额外的列,并避免两次扫描“销售”,但是我会有两个不同的列,而不是像我正在寻找的那样:
SELECT date,
store,
count(sale_price) AS sales_count,
sum(count(sale_price)) over(PARTITION BY date) AS sales_per_day
FROM sales
GROUP BY 1, 2
--->
date | store | sales_count | sales_per_day
---------------+-------------+--------------+-----------------
2021-09-01 | foo | 3 | 4
2021-09-01 | bar | 1 | 4
2021-09-02 | foo | 1 | 3
2021-09-02 | bar | 2 | 3
etc...
是否有可能在不扫描两次的情况下实现我想要做的事情?最后两列(sales_count
和sales_per_day
)可以以某种方式合并吗?
提前感谢您的帮助。
【问题讨论】:
我认为您需要 GROUP BY GROUPING SETS 语法。这是一个很好的例子,一目了然,我认为:sqlservertutorial.net/sql-server-basics/… @JS 有意思,我去看看谢谢 @JS 天哪,太棒了!我已经在 presto 中写了大约 2 年的查询,但我不知道这个东西存在。您应该将其设为答案,以便我将其标记为已接受。 【参考方案1】:您可以使用GROUPING SETS
、CUBE
和ROLLUP
在同一查询中的不同级别进行聚合。您还可以使用GROUPING
操作来确定给定输出行的组中考虑了哪些列:
WITH data(day, store, sale_price) AS (
VALUES
(DATE '2021-09-01', 'foo', 15),
(DATE '2021-09-01', 'foo', 10),
(DATE '2021-09-01', 'foo', 10),
(DATE '2021-09-01', 'bar', 5),
(DATE '2021-09-02', 'foo', 30),
(DATE '2021-09-02', 'bar', 40),
(DATE '2021-09-02', 'bar', 20)
)
SELECT day,
if(grouping(store) = 1, '<aggregate>', store),
count(sale_price) as sales_count
FROM data
GROUP BY GROUPING SETS ((day), (day, store))
ORDER BY day, grouping(store)
【讨论】:
以上是关于(Presto)SQL:按列“A”和“B”以及计数列“C”分组,但也包括仅按“A”分组的“C”计数的主要内容,如果未能解决你的问题,请参考以下文章
Presto on Spark:通过 Spark 来扩展 Presto