Google bigquery bigquery标准中按汇总分组的分组函数
我知道bigquery遗留SQL有一个grouping()函数,用于按汇总分组以区分空值Google bigquery bigquery标准中按汇总分组的分组函数,google-bigquery,Google Bigquery,我知道bigquery遗留SQL有一个grouping()函数,用于按汇总分组以区分空值 标准SQL是否有类似的函数?或者有没有其他方法可以在不首先用硬编码值替换的情况下区分空值?根据文档,可以在StandardSQL中找到。其定义如下: GROUP BY ROLLUP返回GROUP BY对 汇总列表中的表达式,每个表达式都称为分组 设置对于汇总列表(a、b、c),分组集为(a、b、c), (a,b),(a),() 您可以按如下语法使用它: SELECT * FROM `project_id.
标准SQL是否有类似的函数?或者有没有其他方法可以在不首先用硬编码值替换的情况下区分空值?根据文档,可以在StandardSQL中找到。其定义如下: GROUP BY ROLLUP返回GROUP BY对 汇总列表中的表达式,每个表达式都称为分组 设置对于汇总列表(a、b、c),分组集为(a、b、c), (a,b),(a),() 您可以按如下语法使用它:
SELECT * FROM `project_id.dataset.table`
GROUP BY ROLLUP (column)
此外,为了清楚地解释功能,我将使用以下示例(取自文档):
以及产量,
+------+------+-------+
| sku | day | total |
+------+------+-------+
| NULL | NULL | 39.77 |
| 123 | NULL | 28.97 |
| 123 | 1 | 18.98 |
| 123 | 2 | 9.99 |
| 456 | NULL | 8.81 |
| 456 | 1 | 4.56 |
| 456 | 3 | 4.25 |
| 789 | 3 | 1.99 |
| 789 | NULL | 1.99 |
+------+------+-------+
Row sku day sum_per_sku_per_day sum_per_sku sum_all_days_sku
1 123 1 18.98 28.97 39.77
2 456 1 4.56 8.81 39.77
3 123 2 9.99 28.97 39.77
4 789 3 1.99 1.99 39.77
5 456 3 4.25 8.81 39.77
Row sku day total
1 null null 39.53
2 null null 5
3 null 3 5
4 123 null 28.97
5 123 1 18.98
6 123 2 9.99
7 456 null 4.56
8 456 1 4.56
9 789 null 1
10 789 3 1
Row sku day total
1 null null 39.53
2 0 null 5
3 0 3 5
4 123 null 28.97
5 123 1 18.98
6 123 2 9.99
7 456 null 4.56
8 456 1 4.56
9 789 null 1
10 789 3 1
输出可分为三部分进行说明
sku
为空且日期为空时sku
和day
值的总和。在此示例中,所有日期和sku中所有价格的总和为39.77
sku
不为空且day
为空时sku
在所有天内的总和。例如,当sku=123
时,所有天数的总和为28.97
当日期
或sku
均不为空时。
它就像一个正常的总和和分组。它显示特定值对的和
关于第二个问题,如果要更改空值,可以相应地更改每个空值或使用其他方法。下面我使用了以不同的方式输出相同的结果
WITH Sales AS (
SELECT 123 AS sku, 1 AS day, 9.99 AS price UNION ALL
SELECT 123, 1, 8.99 UNION ALL
SELECT 456, 1, 4.56 UNION ALL
SELECT 123, 2, 9.99 UNION ALL
SELECT 789, 3, 1.00 UNION ALL
SELECT 456, 3, 4.25 UNION ALL
SELECT 789, 3, 0.99
),
sum_all AS (
SELECT sum(price) as sum_all_days_sku from Sales
),
sum_per_sku AS (
SELECT sku, ROUND(sum(price),2) AS sum_per_sku, CONCAT("This sum refers to sku =", sku) AS comment FROM Sales GROUP BY sku
),
sum AS (
SELECT sku, day, sum(price) AS sum_per_sku_per_day FROM Sales GROUP BY sku, day
)
SELECT a.sku,a.day,a.sum_per_sku_per_day, b.sum_per_sku, c.sum_all_days_sku
FROM sum a LEFT JOIN sum_per_sku b USING(sku) CROSS JOIN sum_all c
以及产量,
+------+------+-------+
| sku | day | total |
+------+------+-------+
| NULL | NULL | 39.77 |
| 123 | NULL | 28.97 |
| 123 | 1 | 18.98 |
| 123 | 2 | 9.99 |
| 456 | NULL | 8.81 |
| 456 | 1 | 4.56 |
| 456 | 3 | 4.25 |
| 789 | 3 | 1.99 |
| 789 | NULL | 1.99 |
+------+------+-------+
Row sku day sum_per_sku_per_day sum_per_sku sum_all_days_sku
1 123 1 18.98 28.97 39.77
2 456 1 4.56 8.81 39.77
3 123 2 9.99 28.97 39.77
4 789 3 1.99 1.99 39.77
5 456 3 4.25 8.81 39.77
Row sku day total
1 null null 39.53
2 null null 5
3 null 3 5
4 123 null 28.97
5 123 1 18.98
6 123 2 9.99
7 456 null 4.56
8 456 1 4.56
9 789 null 1
10 789 3 1
Row sku day total
1 null null 39.53
2 0 null 5
3 0 3 5
4 123 null 28.97
5 123 1 18.98
6 123 2 9.99
7 456 null 4.56
8 456 1 4.56
9 789 null 1
10 789 3 1
如图所示,输出与GROUP BY ROLLUP()的总和相同。但是,它以列的形式显示
更新:
如果部分sku
行为空,如果在使用ROLLUP()之前不处理空值,就会有点混乱
使用下面的示例数据和查询
WITH Sales AS (
SELECT 123 AS sku, 1 AS day, 9.99 AS price UNION ALL
SELECT 123, 1, 8.99 UNION ALL
SELECT 456, 1, 4.56 UNION ALL
SELECT 123, 2, 9.99 UNION ALL
SELECT 789, 3, 1.00 UNION ALL
SELECT null, 3, 1 UNION ALL
SELECT null, 3, 1 UNION ALL
SELECT null, 3, 1 UNION ALL
SELECT null, 3, 1 UNION ALL
SELECT null, 3, 1
)
SELECT
sku,
day,
SUM(price) AS total
FROM Sales
GROUP BY ROLLUP(sku, day)
ORDER BY sku, day;
注意,有5行sku
为NULL
,引用和为5。以及产量,
+------+------+-------+
| sku | day | total |
+------+------+-------+
| NULL | NULL | 39.77 |
| 123 | NULL | 28.97 |
| 123 | 1 | 18.98 |
| 123 | 2 | 9.99 |
| 456 | NULL | 8.81 |
| 456 | 1 | 4.56 |
| 456 | 3 | 4.25 |
| 789 | 3 | 1.99 |
| 789 | NULL | 1.99 |
+------+------+-------+
Row sku day sum_per_sku_per_day sum_per_sku sum_all_days_sku
1 123 1 18.98 28.97 39.77
2 456 1 4.56 8.81 39.77
3 123 2 9.99 28.97 39.77
4 789 3 1.99 1.99 39.77
5 456 3 4.25 8.81 39.77
Row sku day total
1 null null 39.53
2 null null 5
3 null 3 5
4 123 null 28.97
5 123 1 18.98
6 123 2 9.99
7 456 null 4.56
8 456 1 4.56
9 789 null 1
10 789 3 1
Row sku day total
1 null null 39.53
2 0 null 5
3 0 3 5
4 123 null 28.97
5 123 1 18.98
6 123 2 9.99
7 456 null 4.56
8 456 1 4.56
9 789 null 1
10 789 3 1
如上所示,第二和第三个输出的行与空值相关,而不是与ROLLUP()
的输出相关。为了区分它,在最终查询中使用这些值之前,必须先处理这些值。特别是,我在sku
为空的地方指定了零。然后查询数据,如下所示:
WITH Sales AS (
SELECT 123 AS sku, 1 AS day, 9.99 AS price UNION ALL
SELECT 123, 1, 8.99 UNION ALL
SELECT 456, 1, 4.56 UNION ALL
SELECT 123, 2, 9.99 UNION ALL
SELECT 789, 3, 1.00 UNION ALL
SELECT null, 3, 1 UNION ALL
SELECT null, 3, 1 UNION ALL
SELECT null, 3, 1 UNION ALL
SELECT null, 3, 1 UNION ALL
SELECT null, 3, 1
),
data as (
SELECT IFNULL(sku , 0) as sku, day, price from Sales
)
SELECT
sku,
day,
SUM(price) AS total
FROM data
GROUP BY ROLLUP(sku, day)
ORDER BY sku, day;
以及产量,
+------+------+-------+
| sku | day | total |
+------+------+-------+
| NULL | NULL | 39.77 |
| 123 | NULL | 28.97 |
| 123 | 1 | 18.98 |
| 123 | 2 | 9.99 |
| 456 | NULL | 8.81 |
| 456 | 1 | 4.56 |
| 456 | 3 | 4.25 |
| 789 | 3 | 1.99 |
| 789 | NULL | 1.99 |
+------+------+-------+
Row sku day sum_per_sku_per_day sum_per_sku sum_all_days_sku
1 123 1 18.98 28.97 39.77
2 456 1 4.56 8.81 39.77
3 123 2 9.99 28.97 39.77
4 789 3 1.99 1.99 39.77
5 456 3 4.25 8.81 39.77
Row sku day total
1 null null 39.53
2 null null 5
3 null 3 5
4 123 null 28.97
5 123 1 18.98
6 123 2 9.99
7 456 null 4.56
8 456 1 4.56
9 789 null 1
10 789 3 1
Row sku day total
1 null null 39.53
2 0 null 5
3 0 3 5
4 123 null 28.97
5 123 1 18.98
6 123 2 9.99
7 456 null 4.56
8 456 1 4.56
9 789 null 1
10 789 3 1
请注意,现在更容易理解,因为我们知道0
表示空数据。如果group by rollup之前的初始表(sku为空)中已经存在空值,会发生什么情况。有没有办法区分源空值和求和空值?@Rendell1,我已经更新了我的答案,并做了进一步的解释。请考虑接受和投票的答案。我希望有一种方法,没有硬编码的价值。如果我事先不知道列的可能值,这可能会适得其反。但我想不出其他解决办法,所以我会给你答案。非常感谢。