Google BigQuery相同日期范围过滤返回不同结果问题排查
结论
- 查询1返回的是完整的2019年5月全量数据,结果正确。
- 你观察到的
<=运算符“异常”不是BigQuery的功能bug,是对时间类型的隐式转换规则、字段精度理解偏差导致的。
结果不匹配的根本原因
bigquery-public-data.pypi.file_downloads表的timestamp字段是微秒级精度的TIMESTAMP类型,存储的是精确到微秒的时间点,不是仅包含年月日的日期值:
- 当你把字符串
'2019-05-31'和TIMESTAMP类型字段做比较时,BigQuery会自动将字符串隐式转换为时间值2019-05-31 00:00:00.000000 UTC,也就是5月31日的零点整。此时timestamp <= '2019-05-31'的实际过滤逻辑是「时间早于或等于5月31日零点」,直接漏掉了5月31日零点之后整整24小时的所有数据,实际效果和timestamp < '2019-05-31'完全一致,这就是你觉得<=运算符失效的原因。 - 你观察到
>=运算符运行正常,是因为timestamp >= '2019-05-01'隐式转换后对应的边界是2019-05-01 00:00:00.000000 UTC,刚好是5月的起始时间点,不会遗漏5月1日当天的数据,因此看起来表现正常。 - 查询1使用的过滤条件
timestamp > '2019-04-30' AND timestamp < '2019-06-01',隐式转换后的时间范围是晚于4月30日零点、早于6月1日零点,刚好完整覆盖5月1日零点到5月31日23:59:59.999999的全部5月数据,没有遗漏也没有冗余,因此结果正确。
时间范围过滤的最佳实践
针对TIMESTAMP类型字段做按月过滤时,优先使用左闭右开的区间写法,既能保证数据完整,又能充分利用BigQuery的分区裁剪能力降低扫描量:
WHERE timestamp >= '2019-05-01' AND timestamp < '2019-06-01'
如果一定要使用<=作为右边界,需要明确写全天的最后时间点,或者先将timestamp转换为DATE类型再比较,但后者会导致分区裁剪失效,扫描成本更高:
-- 写全右边界时间精度 WHERE timestamp >= '2019-05-01' AND timestamp <= '2019-05-31 23:59:59.999999' -- 转换为日期类型比较 WHERE DATE(timestamp) BETWEEN '2019-05-01' AND '2019-05-31'
内容的提问来源于stack exchange,提问作者yf879
相关产品推荐
相关产品推荐

