Google bigquery 如何在BigQuery表中选择最新的分区?

Google bigquery 如何在BigQuery表中选择最新的分区?,google-bigquery,Google Bigquery,我试图从日期分区的BigQuery表中的最新分区中选择数据,但该查询仍然从整个表中读取数据 我已经试过了(据我所知,BigQuery不支持QUALIFY): 但这不起作用,会读取所有行 SELECT col from table WHERE _PARTITIONTIME = TIMESTAMP('YYYY-MM-DD') 其中,'YYYY-MM-DD'是一个特定的日期 但是,我以后需要运行这个脚本,但是表更新(以及\u PARTITIONTIME)是不规则的。有没有办法只从BigQuery中最

我试图从日期分区的BigQuery表中的最新分区中选择数据,但该查询仍然从整个表中读取数据

我已经试过了(据我所知,BigQuery不支持
QUALIFY
):

但这不起作用,会读取所有行

SELECT col from table WHERE _PARTITIONTIME = TIMESTAMP('YYYY-MM-DD')
其中,
'YYYY-MM-DD'
是一个特定的日期

但是,我以后需要运行这个脚本,但是表更新(以及
\u PARTITIONTIME
)是不规则的。有没有办法只从BigQuery中最新的分区提取数据

2019年10月更新

对和的支持目前处于测试阶段(截至2019年10月)

您可以提交多个用分号分隔的语句,BigQuery现在可以运行它们了

见下面的例子

DECLARE max_date TIMESTAMP;
SET max_date = (
  SELECT MAX(_PARTITIONTIME) FROM project.dataset.partitioned_table`);

SELECT * FROM `project.dataset.partitioned_table`
WHERE _PARTITIONTIME = max_date;
为那些喜欢在不检查上下文的情况下进行向下投票的人更新

我认为,这个答案被接受是因为它解决了OP的主要问题
是否有一种方法可以只从BigQuery中最新的分区提取数据?
并且在评论中提到,很明显,BQ引擎仍然扫描所有行,但只返回基于最近分区的结果。正如问题注释中已经提到的-
仍然可以通过编写逻辑脚本轻松解决问题-首先获取子查询的结果,然后在最终查询中使用它

试一试


列出包含以下内容的所有分区:

#standardSQL
SELECT
  _PARTITIONTIME as pt
FROM
  `[DATASET].[TABLE]`
GROUP BY 1
然后选择最新的时间戳

祝你好运:)


很抱歉,我在谷歌搜索中发现了这个老问题,我认为公认的答案是误导性的

从和运行的测试中我可以看出,接受的答案将删除分区,因为子查询用于确定最近的分区:

需要对查询的多个阶段求值以解析谓词的复杂查询(例如内部查询或子查询)将不会从查询中删除分区

因此,尽管建议的答案将提供您期望的结果,但它仍然会查询所有分区。它将忽略所有较旧的分区,只查询最新的分区

诀窍是使用或多或少的常量进行比较,而不是使用子查询。例如,如果
\u PARTITIONTIME
不是不规则的,而是每天的,请尝试通过获取昨天的分区来修剪分区,如下所示:

SELECT * FROM [dataset.partitioned_table]
    WHERE _PARTITIONDATE = DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)
当然,这并不总是最新的数据,但在我的情况下,这恰好足够接近。如果需要今天的数据,请使用
INTERVAL 0 DAY
,而不必担心查询将在当天尚未创建分区的部分返回0个结果


我很高兴知道是否有更好的解决办法来获得最新的分区

我找到了解决这个问题的方法。您可以使用with语句,选择最后几个分区并过滤掉结果。我认为这是更好的方法,因为:

  • 您不受固定分区日期的限制(如今天-1天)。它将始终从给定范围中获取最新分区
  • 它将只扫描最后几个分区,而不是整个表
  • 最后3个分区扫描的示例:

    WITH last_three_partitions as (select *, _PARTITIONTIME as PARTITIONTIME 
        FROM dataset.partitioned_table 
        WHERE  _PARTITIONTIME > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 3 DAY))
    SELECT col1, PARTITIONTIME from last_three_partitions 
    WHERE PARTITIONTIME = (SELECT max(PARTITIONTIME) from last_three_partitions)
    

    您可以利用
    \uuuu TABLES\uuuu
    表列表来避免重新扫描所有内容或希望最新分区在~3天前。我做了
    split
    ordinal
    的工作,以防我的表前缀由于某种原因在表名中出现多次

    这应该适用于
    \u PARTITIONTIME
    \u TABLE\u SUFFIX

    select * from `project.dataset.tablePrefix*` 
    where _PARTITIONTIME = (
        SELECT split(table_id,'tablePrefix')[ordinal(2)] FROM `project.dataset.__TABLES__` 
        where table_id like 'tablePrefix%'
        order by table_id desc limit 1)
    

    我在一个不太受欢迎的问题中得到了这个答案,所以将它复制到这里,因为它是相关的(这个问题的页面浏览量越来越多):

    米哈伊尔的回答如下(处理公共数据):

    但问题似乎是这样的:

    SELECT MAX(views)
    FROM `fh-bigquery.wikipedia_v3.pageviews_2019` 
    WHERE DATE(datehour) = (SELECT DATE(MAX(datehour)) FROM `fh-bigquery.wikipedia_v3.pageviews_2019` WHERE wiki='es')     
    AND wiki='es'
    # 50.6 GB processed
    
    。。。但对于小于50.6GB的方式

    您现在需要的是某种脚本,分两步执行:

    max_date = (SELECT DATE(MAX(datehour)) FROM `fh-bigquery.wikipedia_v3.pageviews_2019` WHERE wiki='es')   
    
    ;
    
    SELECT MAX(views)
    FROM `fh-bigquery.wikipedia_v3.pageviews_2019` 
    WHERE DATE(datehour) = {{max_date}}
    AND wiki='es'
    # 115.2 MB processed
    

    您必须在BigQuery之外编写脚本,或者等待消息。

    这是一种折衷方案,它可以只查询几个分区,而不必求助于脚本,也不会因缺少固定日期的分区而失败

    WITH latest_partitions AS (
      SELECT *, _PARTITIONDATE AS date
      FROM `myproject.mydataset.mytable`
      WHERE _PARTITIONDATE > DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
    )
    SELECT
      *
    FROM
      latest_partitions
    WHERE
      date = (SELECT MAX(date) FROM latest_partitions)
    

    请注意,这将停止查询结果缓存(可能会影响成本)。此答案解决了
    是否有办法仅从BigQuery中的最新分区提取数据?
    问题!很明显,引擎仍然扫描所有行,但只基于最近的分区返回结果。正如问题注释中已经提到的-
    通过编写逻辑脚本仍然很容易解决问题-首先获取子查询的结果,然后在最终查询中使用它
    当您手动探索数据时,脚本编写方法非常好,但在使用api客户机并将结果存储在目标表中时不起作用。在这些情况下,您仍然必须作为两个作业运行,第一个作业的输出用作第二个作业的输入,不幸的是:
    configuration.query.destinationTable无法为脚本设置
    @LarsHaugseth您可以在脚本中使用INSERT或CREATE和REPLACE来避免无法设置目标表DECLARE的缺点是您无法在视图中使用它。您可以澄清一下它是如何工作的吗?有什么问题吗?我已经在下面做了评论,但这两个查询都不是只从最新的分区读取的。当我显式地键入last _partitiontime时,查询读取18MB。但当我尝试下面两个查询中的任何一个时,它们的读数为15.4GB。我现在知道了。谢谢你的更新!理解原因很有趣@felipe hoffa提到了一些关于缓存的内容,但这并不清楚。这样它就可以工作了,但有趣的是为什么它不能内联工作——在一个问题中,我想我现在明白了。很明显,但这是我的猜测。。。所以,当使用值时,分区会涉及get,bq引擎知道要扫描什么和什么
    SELECT MAX(views)
    FROM `fh-bigquery.wikipedia_v3.pageviews_2019` 
    WHERE DATE(datehour) = DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)     
    AND wiki='es' 
    # 122.2 MB processed
    
    SELECT MAX(views)
    FROM `fh-bigquery.wikipedia_v3.pageviews_2019` 
    WHERE DATE(datehour) = (SELECT DATE(MAX(datehour)) FROM `fh-bigquery.wikipedia_v3.pageviews_2019` WHERE wiki='es')     
    AND wiki='es'
    # 50.6 GB processed
    
    max_date = (SELECT DATE(MAX(datehour)) FROM `fh-bigquery.wikipedia_v3.pageviews_2019` WHERE wiki='es')   
    
    ;
    
    SELECT MAX(views)
    FROM `fh-bigquery.wikipedia_v3.pageviews_2019` 
    WHERE DATE(datehour) = {{max_date}}
    AND wiki='es'
    # 115.2 MB processed
    
    WITH latest_partitions AS (
      SELECT *, _PARTITIONDATE AS date
      FROM `myproject.mydataset.mytable`
      WHERE _PARTITIONDATE > DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)
    )
    SELECT
      *
    FROM
      latest_partitions
    WHERE
      date = (SELECT MAX(date) FROM latest_partitions)