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

如何在BigQuery中查询当前ID对应其余ID的最大日期

高性能实现方案

原方案性能瓶颈核心是将全量明细行与ID维度聚合结果做CROSS JOIN,产生的笛卡尔积行数为「明细总行数 * ID数量」,数据量越大性能损耗越严重,可通过提前聚合+轻量计算的思路彻底避免笛卡尔积操作。

优化核心思路

  • 先按ID维度做一次聚合,得到每个ID对应的最大日期,仅保留ID数量级的行数,远小于明细行数量
  • 在ID维度的小结果集上计算每个ID对应的「其他ID最大日期」,无大表关联开销
  • 将计算好的两个日期值关联回原明细行即可得到最终结果

通用兼容实现(支持所有主流SQL引擎)

WITH t AS (
    -- 此处替换为你的原表逻辑
    SELECT 1 AS id, rep_date FROM UNNEST(GENERATE_DATE_ARRAY('2021-09-01','2021-09-09', INTERVAL 1 DAY)) rep_date
    UNION ALL 
    SELECT 2 AS id, rep_date FROM UNNEST(GENERATE_DATE_ARRAY('2021-08-20','2021-09-03', INTERVAL 1 DAY)) rep_date
    UNION ALL 
    SELECT 3 AS id, rep_date FROM UNNEST(GENERATE_DATE_ARRAY('2021-08-25','2021-09-05', INTERVAL 1 DAY)) rep_date    
),
-- 按ID聚合得到每个ID的最大日期,行数为ID总数
t_id_max AS (
    SELECT id, MAX(rep_date) AS id_max_date
    FROM t
    GROUP BY 1
),
-- 计算全局最大日期统计值,仅返回1行
global_date_stats AS (
    SELECT
        MAX(id_max_date) AS first_max,
        MAX(CASE WHEN id_max_date < (SELECT MAX(id_max_date) FROM t_id_max) THEN id_max_date END) AS second_max,
        COUNT(DISTINCT CASE WHEN id_max_date = (SELECT MAX(id_max_date) FROM t_id_max) THEN id END) AS first_max_id_count
    FROM t_id_max
),
-- 为每个ID计算其他ID的最大日期,仅处理ID数量级的行数
t_id_with_other_max AS (
    SELECT
        a.id,
        a.id_max_date,
        CASE
            WHEN a.id_max_date < b.first_max THEN b.first_max
            WHEN b.first_max_id_count > 1 THEN b.first_max
            ELSE b.second_max
        END AS max_date_over_others
    FROM t_id_max a
    CROSS JOIN global_date_stats b
)
-- 关联回原明细行得到结果
SELECT 
    a.id,
    a.rep_date,
    b.id_max_date AS max_date,
    b.max_date_over_others
FROM t a
JOIN t_id_with_other_max b USING(id)

简洁写法(支持窗口函数EXCLUDE语法的引擎,如BigQuery、PostgreSQL 11+)

WITH t AS (
    -- 此处替换为你的原表逻辑
    SELECT 1 AS id, rep_date FROM UNNEST(GENERATE_DATE_ARRAY('2021-09-01','2021-09-09', INTERVAL 1 DAY)) rep_date
    UNION ALL 
    SELECT 2 AS id, rep_date FROM UNNEST(GENERATE_DATE_ARRAY('2021-08-20','2021-09-03', INTERVAL 1 DAY)) rep_date
    UNION ALL 
    SELECT 3 AS id, rep_date FROM UNNEST(GENERATE_DATE_ARRAY('2021-08-25','2021-09-05', INTERVAL 1 DAY)) rep_date    
),
t_id_max AS (
    SELECT id, MAX(rep_date) AS id_max_date
    FROM t
    GROUP BY 1
),
t_id_with_other_max AS (
    SELECT
        id,
        id_max_date,
        MAX(id_max_date) OVER (
            ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
            EXCLUDE CURRENT ROW
        ) AS max_date_over_others
    FROM t_id_max
)
SELECT a.id, a.rep_date, b.id_max_date max_date, b.max_date_over_others
FROM t a
JOIN t_id_with_other_max b USING(id)

性能提升说明

  • 原方案复杂度为O(N*M),N为明细行数,M为ID数量,新方案复杂度为O(N+M),ID越多性能提升越明显
  • 避免了大表笛卡尔积的生成,内存占用也会大幅降低

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 03:54:00