错误:TABLE_QUERY 表达式无法查询 BigQuery 表

Posted

技术标签:

【中文标题】错误:TABLE_QUERY 表达式无法查询 BigQuery 表【英文标题】:Error: TABLE_QUERY expressions cannot query BigQuery tables 【发布时间】:2016-04-17 06:41:32 【问题描述】:

这是关于乔丹的后续问题,请在此处回答:Weird error in BigQuery

我曾经在“Table_Query”中查询参考表以退出一段时间。现在,在 Joradan 所指的最近发生的变化之后,我们的许多查询都被打破了......我想向社区寻求替代解决方案的建议。

我有包含事件的表(“MyTable_YYYYMMDD”)。我想查询特定(或多个)活动期间的数据。该活动的周期存储在包含所有活动数据(ID、StartCampaignDate、EndCampaignDate)的表中。为了仅查询相关表,我们使用 Table_Query(),并在 TableQuery() 中根据活动数据构建所有相关表名称的列表。 此查询以不同的参数以各种形式多次运行。使用通配符函数(而不是查询整个数据集)的原因是性能、执行成本和维护成本。因此,让它查询所有表并仅过滤结果并不是一种选择,因为它会导致执行成本过高。

示例查询如下所示:

SELECT
  *
FROM
  TABLE_QUERY([MyProject:MyDataSet] 'table_id IN  
  (SELECT CONCAT("MyTable_",STRING(Year*100+Month)) TBL_NAME  
    FROM DWH.Dim_Periods P  
    CROSS JOIN DWH.Campaigns AS LC  
    WHERE ID IN ("86254e5a-b856-3b5a-85e1-0f5ab3ff20d6") 
    AND DATE(P.Date) BETWEEN DATE(StartCampaignDate) AND DATE(EndCampaignDate))')

现在坏了... 我的问题 - 您应该查询哪些表的信息存储在引用表中,当不再允许“TableQuery”查询引用表时,您将如何仅查询相关表(分区)?

非常感谢

【问题讨论】:

【参考方案1】:

我看到的“简单”方式是将其分为两个步骤 第 1 步 - 构建将用于过滤 table_id 的列表

SELECT GROUP_CONCAT_UNQUOTED(
                   CONCAT('"',"MyTable_",STRING(Year*100+Month),'"')
       ) TBL_NAME_LIST 
FROM DWH.Dim_Periods P  
CROSS JOIN DWH.Campaigns AS LC  
WHERE ID IN ("86254e5a-b856-3b5a-85e1-0f5ab3ff20d6") 
AND DATE(P.Date) BETWEEN DATE(StartCampaignDate) AND DATE(EndCampaignDate)

注意查询中的更改以将结果转换为您将在步骤 2 中使用的列表

第 2 步 - 最终查询

SELECT
  *
FROM
  TABLE_QUERY([MyProject:MyDataSet], 
              'table_id IN (<paste list (TBL_NAME_LIST) built in first query>)')

上述步骤很容易在您可能使用的任何客户端中实施 如果您在 BigQuery Web UI 中使用它 - 这会让您做一些额外的手动“移动”,您可能会对此不满意

我的答案很明显,你很可能已经有了这个选项,但想提一下

【讨论】:

谢谢,我们确实考虑过这个解决方案。但是,我更喜欢避免多步骤查询......我担心维护会随着时间的推移变得复杂,因为逻辑分散在几个地方,并且过程中有更多可能的故障点。 如果您正在寻找您所要求的问题的解决方法 - 这就是您所拥有的,而且您不会得到一步解决方案,因为我可以告诉您。如果您想向 Google 团队提出观点或要求 - 您最好使用 code.google.com/p/google-bigquery :o) 这样我们就不会浪费时间回答,即使我喜欢回答并且对此没有任何问题 - 更多的是指向您到正确的渠道 Mikahil,我没有将 NN 的评论视为试图表达观点的人。他只是指出您的解决方案是次优的,据我所知,他有一个有效的论点。您的解决方案的另一个问题是它也会影响查询性能。希望有另一种解决方法,或者 Google 最终会提供一种解决方法【参考方案2】:

这不是理想的解决方案。但它似乎完成了这项工作。

在我之前的查询中,我将 ID 列表作为参数传递给构建查询的外部进程。我希望这个过程不知道查询中实现的任何逻辑。

最终我们想出了这个解决方案:

我们不是传递一个 ID 列表,而是传递一个 JSON,其中包含每个 ID 的相关元数据。我们在 Table_Query() 函数中解析这个 JSON。因此,我们不是查询物理引用表,而是查询我们放入 JSON 中的某种“表变量”。 下面是一个在公共数据集上运行的示例查询,演示了此解决方案。

    SELECT
  YEAR,
  COUNT (*) CNT
FROM
  TABLE_QUERY([fh-bigquery:weather_gsod], 'table_id in
(Select table_id
From
(Select table_id,concat(Right(table_id,4),"0101") as TBL_Date from [fh-bigquery:weather_gsod.__TABLES_SUMMARY__]
where table_id Contains "gsod"
)TBLs
CROSS JOIN 
(select 
Regexp_Replace(Regexp_extract(SPLIT(DatesInput,","),r"\"fromDate\":\"(\d\d\d\d-\d\d-\d\d)\""),"-","") as fromDate,
Regexp_Replace(Regexp_extract(SPLIT(DatesInput,","),r"\"toDate\":\"(\d\d\d\d-\d\d-\d\d)\""),"-","") as toDate,
FROM
(Select
"[  
        
         \"CycleID\":\"123456\",
         \"fromDate\":\"1929-01-01\",
         \"toDate\":\"1950-01-10\"
      ,  
         \"CycleID\":\"123456\",
         \"fromDate\":\"1970-02-01\",
         \"toDate\":\"2000-02-10\"
      
   ]"
   as DatesInput)) RefDates
   WHERE TBLs.TBL_Date>=RefDates.fromDate
   AND TBLs.TBL_Date<=RefDates.toDate
)')
GROUP BY
  YEAR
ORDER BY
  YEAR

此解决方案并不理想,因为它需要外部进程来了解存储在引用表中的数据。 理想情况下,BigQuery 团队将重新启用这一非常有用的功能。

【讨论】:

以上是关于错误:TABLE_QUERY 表达式无法查询 BigQuery 表的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 中的表函数和 FLATTEN

有没有一种简单的方法可以根据 BigQuery 中的时区差异生成 table_query?

使用 REGEX 表达式了解查询

BigQuery:TABLE_QUERY,但表之间的列不同

Google BigQuery:TABLE_QUERY 和 TABLE_DATE_RANGE

BI Engine 模式不完整,原因是内部错误