收集对日期分区表的查询的每日结果

Posted

技术标签:

【中文标题】收集对日期分区表的查询的每日结果【英文标题】:Collecting per-day results for queries over date-partitioned tables 【发布时间】:2017-12-21 15:41:10 【问题描述】:

我在 BigQuery 中有一些名称为 counts_20171220 的表,其中的行采用这种格式(每个日期每个 contentId 只有一行):

| contentId | views |
+-----------+-------+
| cb32edc0  | 728324|
| 52cbb1ff  | 643220|
...

我想为给定时间范围内的给定contentId 生成查看计数列表,没有间隙,例如:

|       date |  views |
+------------+--------+
| 2017-12-01 |   NULL | -- or 0
| 2017-12-02 |   NULL | -- or 0
| 2017-12-03 | 728314 |
| 2017-12-04 | 328774 |
| 2017-12-05 |  28242 |
...
| 2017-12-20 |   NULL | -- or 0

为了做到这一点,我想我需要使用*_table_suffix,但我无法弄清楚如何包含没有该contentId 条目的日期。我得到的最接近的是这个查询:

#standardSQL
SELECT
  _table_suffix AS date,
  ARRAY_AGG(views) AS views
FROM
  `test.counts_*`
WHERE
  _table_suffix BETWEEN '20171201' AND '20171220'
  AND contentId = 'cb32edc0'
GROUP BY
  _table_suffix,
  contentId
ORDER BY
  date

这个查询的问题是

    它不包含所有日期的行,仅包含表中包含contentId 'cb32edc0' 条目的日期 由于它的结构方式,我需要使用(这里没用的)聚合函数来提取views

我应该如何构建这样的查询?我很乐意获得有关此查询的具体帮助以及有关如何实现此类查询日期分区表的一般指示。

【问题讨论】:

【参考方案1】:

这应该可行,假设每个日期至少有一行:

SELECT
  PARSE_DATE('%Y%m%d', _TABLE_SUFFIX) AS date,
  IFNULL(MAX(IF(contentId = 'cb32edc0', views, NULL)), 0) AS views
FROM `test_counts_*`
WHERE _TABLE_SUFFIX BETWEEN '20171201' AND '20171220'
GROUP BY date;

它不是显式过滤与所需contentId 不匹配的行,而是使用带有聚合函数的条件将它们从结果中排除。如果组中没有具有所需contentId 的行,IFNULL 确保表达式返回0 而不是NULL

【讨论】:

谢谢!这实际上相当优雅!

以上是关于收集对日期分区表的查询的每日结果的主要内容,如果未能解决你的问题,请参考以下文章

深入理解Hive分区与分桶

比较两个日期分区上的同一行

oracle数据量巨大表查询时间太长,sqlplus有的不能spool出结果

多日期数据加载到 BigQuery 分区表中

需要关于基于非日期列和日期分区在 bigquery 中拆分表的建议

oracle 中查询按某种要求条件查询结果,如何能够提高效率?