You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BigQuery中按<=各唯一日期分组的可扩展实现方案咨询

可扩展的BigQuery累计统计方案

需求说明

我们有示例数据表t1,需要生成每个唯一日期对应一行的统计结果:对每个日期,统计该日期及之前所有记录的行数、stat1总和、stat2总和。原方案通过硬编码日期实现,无法适配数据中新增的日期,缺乏扩展性,需要自动提取t1中的唯一gameDate完成统计。

示例数据表t1

WITH t1 AS (
  SELECT '2022-12-01' AS gameDate, 3 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-01' AS gameDate, 2 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-01' AS gameDate, 5 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 4 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 2 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 1 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 2 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 4 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 4 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 2 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 1 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 2 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 1 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 4 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 3 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 4 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-06' AS gameDate, 1 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-06' AS gameDate, 3 AS stat1, 7 AS stat2
)

解决方案

推荐两种可扩展的BigQuery实现方式:

方法1:交叉连接生成日期维度

先提取t1中所有唯一的gameDate作为日期维度表,再和原表关联,过滤出gameDate <= rowDate的记录后分组统计,逻辑直观易懂:

WITH t1 AS (
  SELECT '2022-12-01' AS gameDate, 3 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-01' AS gameDate, 2 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-01' AS gameDate, 5 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 4 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 2 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 1 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 2 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 4 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 4 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 2 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 1 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 2 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 1 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 4 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 3 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 4 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-06' AS gameDate, 1 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-06' AS gameDate, 3 AS stat1, 7 AS stat2
),
unique_dates AS (
  SELECT DISTINCT gameDate AS rowDate FROM t1
)
SELECT
  ud.rowDate,
  COUNT(t1.gameDate) AS ct,
  SUM(t1.stat1) AS sumStat1,
  SUM(t1.stat2) AS sumStat2
FROM unique_dates ud
LEFT JOIN t1 ON t1.gameDate <= ud.rowDate
GROUP BY ud.rowDate
ORDER BY ud.rowDate ASC;

方法2:窗口函数(高效实现)

先按日期分组计算每日的统计值,再用累计窗口函数计算到当前日期的总和,避免了交叉连接的笛卡尔积,性能更优,适合大数据量场景:

WITH t1 AS (
  SELECT '2022-12-01' AS gameDate, 3 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-01' AS gameDate, 2 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-01' AS gameDate, 5 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 4 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 2 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-02' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 1 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 2 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 4 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-03' AS gameDate, 4 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 2 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 1 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 2 AS stat1, 7 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 1 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-04' AS gameDate, 4 AS stat1, 9 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 3 AS stat1, 8 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 3 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-05' AS gameDate, 4 AS stat1, 6 AS stat2 UNION ALL
  SELECT '2022-12-06' AS gameDate, 1 AS stat1, 5 AS stat2 UNION ALL
  SELECT '2022-12-06' AS gameDate, 3 AS stat1, 7 AS stat2
),
daily_stats AS (
  SELECT
    gameDate,
    COUNT(*) AS daily_ct,
    SUM(stat1) AS daily_sumStat1,
    SUM(stat2) AS daily_sumStat2
  FROM t1
  GROUP BY gameDate
)
SELECT
  gameDate AS rowDate,
  SUM(daily_ct) OVER (ORDER BY gameDate) AS ct,
  SUM(daily_sumStat1) OVER (ORDER BY gameDate) AS sumStat1,
  SUM(daily_sumStat2) OVER (ORDER BY gameDate) AS sumStat2
FROM daily_stats
ORDER BY gameDate ASC;

方案对比

  • 方法1:逻辑简单直观,适合小数据集,新增日期会自动纳入统计,无需修改代码。
  • 方法2:性能更高效,尤其当t1数据量较大时,避免了交叉连接带来的计算开销,是更推荐的生产环境方案。

内容的提问来源于stack exchange,提问作者Canovice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 13:35:18