【发布时间】:2021-12-18 21:45:32
【问题描述】:
有没有办法在 BigQuery 中完成以下任务?在 Postgres 等 DB 中支持此语法:
SELECT ProductGroup, Product, Year, Month, AVG(Revenue)
FROM Sales
group by rollup(ProductGroup, Product), rollup(Year, Month)
换句话说,我想要两个汇总的叉积:
ROLLUP(ProductGroup, Product) --> (), (ProductGroup), (ProductGroup, Product)
ROLLUP(Year, Month) --> (), (Year), (Year, Month)
((), (ProductGroup), (ProductGroup, Product)) x ((), (Year), (Year, Month))
= (
(), (ProductGroup), (ProductGroup, Product),
(Year), (Year, ProductGroup), (Year, ProductGroup, Product).
(Year, Month), (Year, Month, ProductGroup), (Year, Month, ProductGroup, Product)
)
在 BQ 中尝试时出现以下错误:
GROUP BY 子句仅在 [2:10] 处没有其他分组元素时才支持 ROLLUP
这里有一些示例图片和数据的更新。
首先,我想复制 Excel 数据透视表的功能。这就是 ROWS 和 COLS 汇总的叉积发挥作用的地方:
请注意,数据透视表有 63 个值单元格。
现在,正确的 SQL 语法如下在冗长的 GROUP BY-only 语法中:
请注意,这也正好产生 63 行(因为我们有一个值列 -- SUM 收入 -- 63 行 x 1 列 = 63 个值单元格)。查询如下:
with sales as (
select 2010 Year, 'Jan' Month, 'Electronics' ProductGroup, 'Phone' Product, 100 Revenue union all
select 2010, 'Jan', 'Electronics', 'Laptop', 200 union all
select 2010, 'Jan', 'Cars', 'Jeep', 250 union all
select 2010, 'Jan', 'Cars', 'Hummer', 105 union all
select 2010, 'Feb', 'Electronics', 'Phone', 110 union all
select 2010, 'Feb', 'Electronics', 'Laptop', 300 union all
select 2010, 'Feb', 'Cars', 'Jeep', 50 union all
select 2010, 'Feb', 'Cars', 'Hummer', 75 union all
select 2010, 'Mar', 'Electronics', 'Phone', 80 union all
select 2010, 'Mar', 'Electronics', 'Laptop', 200 union all
select 2010, 'Mar', 'Cars', 'Jeep', 100 union all
select 2010, 'Mar', 'Cars', 'Hummer', 50 union all
select 2011, 'Jan', 'Electronics', 'Phone', 200 union all
select 2011, 'Jan', 'Electronics', 'Laptop', 300 union all
select 2011, 'Jan', 'Cars', 'Jeep', 100 union all
select 2011, 'Jan', 'Cars', 'Hummer', 200 union all
select 2011, 'Feb', 'Electronics', 'Phone', 300 union all
select 2011, 'Feb', 'Electronics', 'Laptop', 900 union all
select 2011, 'Feb', 'Cars', 'Jeep', 100 union all
select 2011, 'Feb', 'Cars', 'Hummer', 200 union all
select 2011, 'Mar', 'Electronics', 'Phone', 400 union all
select 2011, 'Mar', 'Electronics', 'Laptop', 350 union all
select 2011, 'Mar', 'Cars', 'Jeep', 240 union all
select 2011, 'Mar', 'Cars', 'Hummer', 130
)
-- ROLLUP(ProductGroup, Product), ROLLUP(Year, Month)
--> (), (ProductGroup), (ProductGroup, Product)
--> (Year), (Year, ProductGroup), (Year, ProductGroup, Product)
--> (Year, Month), (Year, Month, ProductGroup), (Year, Month, ProductGroup, Product)
SELECT NULL, NULL, NULL, NULL, AVG(Revenue) FROM Sales UNION ALL -- ()
SELECT ProductGroup, NULL, NULL, NULL, AVG(Revenue) FROM Sales GROUP BY ProductGroup UNION ALL -- (ProductGroup)
SELECT ProductGroup, Product, NULL, NULL, AVG(Revenue) FROM Sales GROUP BY ProductGroup, Product UNION ALL -- (ProductGroup, Product)
SELECT NULL, NULL, Year, NULL, AVG(Revenue) FROM Sales GROUP BY Year UNION ALL -- (Year)
SELECT ProductGroup, NULL, Year, NULL, AVG(Revenue) FROM Sales GROUP BY Year, ProductGroup UNION ALL -- (Year, ProductGroup)
SELECT ProductGroup, Product, Year, NULL, AVG(Revenue) FROM Sales GROUP BY Year, ProductGroup, Product UNION ALL-- (Year, ProductGroup, Product)
SELECT NULL, NULL, Year, Month, AVG(Revenue) FROM Sales GROUP BY Year, Month UNION ALL -- (Year, Month)
SELECT ProductGroup, NULL, Year, Month, AVG(Revenue) FROM Sales GROUP BY ProductGroup, Year, Month UNION ALL -- (ProductGroup, Year, Month)
SELECT ProductGroup, Product, Year, Month, AVG(Revenue) FROM Sales GROUP BY ProductGroup, Product, Year, Month -- (ProductGroup, Product, Year Month)
然而,这个查询对于产品来说真的是一场噩梦——即使是通过程序生成的——因为可能存在order by、subselect、...等,并且将所有这些语句联合起来可能会变成一个可怕的结构(例如,一个 3 行 x 3 列的结构和一个 100 行的 SQL 语句将变成 4^2 * 100 行 sql,而 5x5 将是 5^2 * 100 行,等等。如果我的数学是正确的)。
那么,这样做的正确方法是什么?请注意,在像 Postgres 这样的数据库中,以下内容按原样工作:
SELECT ProductGroup, Product, Year, Month, AVG(Revenue) FROM Sales GROUP BY ROLLUP(ProductGroup, Product), ROLLUP(Year, Month);
如果您想以此为起点,这里是保存的查询:https://console.cloud.google.com/bigquery?sq=260144861653:552549d2a81a47b59df6e3d16ef9bf17。
最后,如果您认为在GROUPING SETS 和CUBE 中添加一个有用的功能,请支持此功能请求:https://issuetracker.google.com/issues/204913323。
【问题讨论】:
-
1) 提供样本数据和所需的输出。 2) 还向我们展示您收到错误的整个查询
-
但我不认为像 GROUP BY a, ROLLUP(b) 这样的语法在 bigQuery 中可用
-
我可能错了,但是-您提出的查询太抽象了,没有太多意义,因此很难提供帮助。您可以对其进行调整以使其实用 - 就像 group by 中的所有字段都显示在 select 中,也许还有一些聚合。理想情况下,如果您提供输入数据和预期输出的简化示例:o)
-
这不是给出一个联合而不是一个叉积吗?
-
@shawnt00 - 很抱歉,如果在这篇文章的不同方面来回出现一些误解:o)
标签: sql google-bigquery combinatorics rollup