【发布时间】:2021-06-04 21:31:36
【问题描述】:
我有一张如下表 -
table_a
id|start_date|end_date
1|2020-01-01|2020-01-05
...
我想使用下表在此数据框中创建一个聚合列
table_b
id|val|date
1|5.0|2020-01-01
1|2.0|2020-01-03
1|6.0|2020-01-08
2|5.0|2020-01-01
3|5.0|2020-01-01
我想要 table_a 中所有 table_b 值总和的聚合列,其中 table_b 的 date 列介于 table_a 的开始日期和结束日期之间。这将如何实现?
所以这个最终的 table_a 将是 -
table_a
id|start_date|end_date|agg_col
1|2020-01-01|2020-01-05|7.0
...
一个后续问题 -
如何根据不同的因素计算多个聚合? (特别是标志和日期范围)我考虑过使用分桶,但来自table_b 的行将落入多个重叠范围。
table_a
id|start_date|end_date
1|2020-01-01|2020-01-05
1|2020-01-03|2020-01-07
1|2020-01-04|2020-01-08
2|2020-01-01|2020-01-05
2|2020-01-03|2020-01-07
2|2020-01-04|2020-01-08
table_b
id|val|date|flag_a|flag_b
1|10.0|2019-12-15|0|0
1|15.0|2019-12-25|0|0
1|5.0|2020-01-01|0|0
1|2.0|2020-01-03|0|4
1|6.0|2020-01-08|3|4
1|4.0|2020-01-18|3|4
2|5.0|2020-01-01|0|3
3|5.0|2020-01-01|0|2
最终输出将具有许多不同的总和聚合列,所有这些列都基于不同的因素。一些可能的聚合可能是 -
table_b date between (START_DATE - 30 days to START_DATE - 15 days)
table_b date between (START_DATE - 180 days to START_DATE - 90 days)
table_b date between (START_DATE - 10 days to START_DATE +5 days AND flag_a=0)
table_b date between (END_DATE + 5 days to END_DATE +20 days AND flag_b=3)
火花函数解决方案会是更快的纯 sql 解决方案,看起来像这样吗?性能是一个巨大的因素,table_a 有 100m 行,table_b 有接近 50b 行。我将运行大约 50 个不同的聚合。
select *,
(select sum(val) from table_b b
where date > a.start_date - 180
and date < a.start_date - 90
and a.id = b.id ) as val_sum_180_90,
...
from table_a a
这样的解决方案?
【问题讨论】:
-
500 亿行的表?我希望它以某种方式进行分区。这是您想要的最糟糕的连接情况,因为它是范围连接。知道大小会有所帮助,因为它说最大的痛点是在 table_b 上。因此,最后需要进行预聚合,并且您将切换连接顺序(希望 table_b 与 table_a 连接而不是相反)。
-
哦等等,其实没那么难(我想)!让我再试一次。
-
@kanielc 是按日期列分区的!
-
信息量很大,所以如果你按照我在下面建议的使用 faster_b 进行操作,那么生成的表格实际上会非常小。在这种情况下,您可以尝试在连接中翻转 faster_b 和 table_a。
标签: scala apache-spark