标准 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 过滤记录的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery:使用标准 SQL 过滤重复字段

如何在标准 SQL 的 BigQuery 中过滤具有 iso 周值的列?

如何比较标准 SQL(BigQuery)中的两个数组?

Bigquery - 如何过滤具有特定条件的记录

标准 sql 查询以获取与另一个表匹配的记录字段(Google BigQuery)

如何避免 BigQuery 中的 Power BI 增量刷新重复查询?