BigQuery按指定日期范围、位置与类型统计去重ID实现方案
BigQuery 高效区间去重统计方案
核心思路是放弃逐天日期展开的逻辑,直接通过日期区间重叠规则匹配有效记录,同时前置清洗冗余的重复、重叠区间数据,将计算量控制在和原表相当的量级。
实现步骤
1. 前置数据清洗(可固化为视图复用)
首先处理表内两类冗余数据,减少后续计算量:
- 完全重复的行(如id=3的三条完全一致的记录)
- 同
id+location+type维度下互相覆盖、相邻的日期区间(如id=1的两条mobile类MO地区记录,区间存在覆盖,可合并为单条连续区间)
清洗逻辑使用窗口函数实现,不需要递归:
WITH cleaned_records AS ( SELECT id, location, type, MIN(start_date) AS merged_start, MAX(end_date) AS merged_end FROM ( SELECT *, -- 标记不连续的新区间分组 COUNTIF(start_date > prev_end + 1) OVER (PARTITION BY id, location, type ORDER BY start_date) AS range_group FROM ( SELECT id, location, type, start_date, end_date, -- 取同维度下上一条记录的结束日期 LAG(end_date) OVER (PARTITION BY id, location, type ORDER BY start_date) AS prev_end FROM ( -- 第一步先去除完全重复的记录 SELECT DISTINCT id, start_date, end_date, location, type FROM `你的项目名.数据集名.表名` ) ) ) GROUP BY id, location, type, range_group )
2. 直接按日期区间重叠规则统计
两个日期区间存在重叠的判断逻辑非常简单,不需要逐天匹配:
记录的开始日期 <= 查询结束日期 且 记录的结束日期 >= 查询开始日期
只要满足该条件,就说明对应id在查询时间范围内有覆盖,直接按维度统计去重id即可。
以你给出的查询2022-01-02至2022-01-03的需求为例,完整查询代码如下:
WITH cleaned_records AS ( -- 上述清洗逻辑,若已固化为视图可直接替换为 FROM `你的清洗后视图名` SELECT id, location, type, MIN(start_date) AS merged_start, MAX(end_date) AS merged_end FROM ( SELECT *, COUNTIF(start_date > prev_end + 1) OVER (PARTITION BY id, location, type ORDER BY start_date) AS range_group FROM ( SELECT id, location, type, start_date, end_date, LAG(end_date) OVER (PARTITION BY id, location, type ORDER BY start_date) AS prev_end FROM ( SELECT DISTINCT id, start_date, end_date, location, type FROM `your_project.your_dataset.your_table` ) ) ) GROUP BY id, location, type, range_group ) SELECT location, type, COUNT(DISTINCT id) AS `count distinct ID` FROM cleaned_records WHERE -- 替换为实际查询的起止日期即可 merged_start <= DATE('2022-01-03') AND merged_end >= DATE('2022-01-02') GROUP BY location, type ORDER BY location, type
结果验证&性能说明
- 基于你提供的样例数据运行上述代码,返回结果和预期完全一致:
| location | type | count distinct ID |
|---|---|---|
| AZ | laptop | 1 |
| AZ | mobile | 1 |
| CA | laptop | 2 |
| CA | mobile | 1 |
| MO | mobile | 1 |
- 性能优势:
- 全程无日期数组join、无逐行展开操作,所有计算为窗口聚合+简单比较运算,计算量和原表数据量持平,完全适配大数据量场景
- 清洗逻辑可固化为视图或定期更新的物理表,查询时仅需做简单过滤即可,不需要每次全表重算
内容的提问来源于stack exchange,提问作者redditor
相关产品推荐
相关产品推荐

