标准 sql 中的 BigQuery 过滤记录
Posted
技术标签:
【中文标题】标准 sql 中的 BigQuery 过滤记录【英文标题】:BigQuery filtering records in standard sql 【发布时间】:2017-02-01 10:26:21 【问题描述】:我正在统计在我们的主页上提交邮政编码的所有访问者。我在旧版 SQL 中提出了以下查询:
SELECT fullVisitorId, visitStartTime
FROM TABLE_DATE_RANGE([ga_sessions_], TIMESTAMP('2017-01-29'), CURRENT_TIMESTAMP())
where hits.page.pagePath = '/broadband/'
and visitStartTime > 1483228800
and hits.type = 'EVENT'
and hits.eventInfo.eventCategory = 'Homepage'
and hits.eventInfo.eventAction = 'Submit Postcode';
然后我想将它转换为标准 SQL 以在 CTE 中使用,并想出了一个看起来不正确的 SQL。
SELECT fullVisitorId, visitStartTime
FROM ``ga_sessions_*``, UNNEST(hits) as h
where
_TABLE_SUFFIX > '2017-01-29'
AND h.page.pagePath = '/broadband/'
and visitStartTime > 1483228800
and h.type = 'EVENT'
and h.eventInfo.eventCategory = 'Homepage'
and h.eventInfo.eventAction = 'Submit Postcode';
第一个处理 327 MB 并返回 4117 个结果,第二个处理 6.98 GB 并返回 60745 个结果。
我查看了migration guide,但事实证明它对我没有多大帮助。
ga_sessions 有 standard schema 的 GA 导入 Bigquery。
【问题讨论】:
【参考方案1】:看起来不同之处在于,使用标准 SQL,当您在 FROM
子句中使用 CROSS JOIN UNNEST(hits)
时,您正在展平 hits
上的表,因此会在结果中添加更多行。更等效的查询是:
#standardSQL
SELECT fullVisitorId, visitStartTime
FROM `ga_sessions_*`
where
_TABLE_SUFFIX > '20170129'
and visitStartTime > 1483228800
and EXISTS(
SELECT 1 FROM UNNEST(hits) h
WHERE h.type = 'EVENT'
and h.page.pagePath = '/broadband/'
and h.eventInfo.eventCategory = 'Homepage'
and h.eventInfo.eventAction = 'Submit Postcode');
【讨论】:
exists 子查询没有加入任何东西?在什么情况下不是真的? 我将 pagePath 谓词移动到 h 可用的子查询。 4699 个结果,处理了 2.84 GB。是 _TABLE_SUFFIX > '20170129' 和 parse_date("%Y%m%d", regexp_extract(_table_suffix, r'.*_(.*)')) >= parse_date("%Y-%m-%d", ' 2017-01-29') 等价物? 我建议您首先在一个特定日期测试您的查询,因此您将 _TABLE_SUFFIX 谓词从查询中取出。一旦您在某一天获得匹配的数字,需要找到等效的 _TABLE_SUFFIX 条件,尽管我在查询中输入的条件与您原始查询中的条件相同。 在 UNNEST(hits) 上存在半联接 - 与您在原始查询中的 UNNEST(hits) 上的 CROSS JOIN 相同。 一天我得到匹配的结果!谢谢!我会接受你的回答。我仍然不完全理解这些差异,我必须阅读更多内容。【参考方案2】:这里发生的事情是 _TABLE_SUFFIX
是一个字符串,所以当你这样做时:
_TABLE_SUFFIX > '2017-01-29'
由于字符串比较与数字比较不同,您最终会选择比预期更多的表。
解决此问题的一种可能方法是将字符串解析为 DATE
类型:
SELECT fullVisitorId, visitStartTime
FROM `ga_sessions*`, UNNEST(hits) as h
where parse_date("%Y%m%d", regexp_extract(_table_suffix, r'.*_(.*)')) >= parse_date("%Y-%m-%d", '2017-01-29')
AND h.page.pagePath = '/broadband/'
and visitStartTime > 1483228800
and h.type = 'EVENT'
and h.eventInfo.eventCategory = 'Homepage'
and h.eventInfo.eventAction = 'Submit Postcode';
parse_date 操作首先将字符串转换为DATE
,然后进行比较。
还请注意,我将通配符选择更改为 ga_sessions,然后使用 REGEX_EXTRACT
我只考虑“_”字符之后的内容。通过这样做,您也可以选择“日内”表。
【讨论】:
我已经修复了您的答案中可能出现的一些错别字,结果现在更接近了,尽管仍然不一样。他们现在都处理相同数量的数据,表明搜索了相同的表格。 (我认为命名空间中没有最新的日内表。)但仍然存在差异:标准 sql 运行 17.3 秒并返回 7749 个结果。遗留sql运行1.4s,返回6623个结果... 嗯,我明白了。您能否在WHERE
子句中添加此条件:and not regexp_contains(_table_suffix, r'intraday')
并查看结果是否匹配?我怀疑盘中表增加了一些以前没有考虑过的行。
它没有改变结果。我的理解是,我们仅将全天结果复制到欧盟地区的命名空间。这是我查询的名称空间,因此它不会有日内结果。预计标准 sql 需要更长的时间吗?以上是关于标准 sql 中的 BigQuery 过滤记录的主要内容,如果未能解决你的问题,请参考以下文章
如何在标准 SQL 的 BigQuery 中过滤具有 iso 周值的列?