如果查询结果在 BigQuery 中没有记录,则显示默认值

Posted

技术标签:

【中文标题】如果查询结果在 BigQuery 中没有记录,则显示默认值【英文标题】:Display default value if query results in no records in BigQuery 【发布时间】:2018-06-05 20:36:01 【问题描述】:

查询可以在 BigQuery 上返回一个空表。发生这种情况的一个例子是,如果我在 BigQuery 上的查询中 join 一堆表并且连接的结果是一个空表,或者如果没有基于 where 子句的匹配项。

这是一个愚蠢的示例查询,它总是以空连接返回:

#standardSQL
WITH query1 AS (
    SELECT 1 AS number, "one" AS message
), query2 AS (
    SELECT 2 AS number, "two" AS message)
SELECT "query result" AS result, query1.* 
FROM query1
JOIN query2 ON query1.number = query2.number;

查询将显示以下输出:Query returned zero records.

如果是这种情况,我想返回一条消息或默认行。但我不知道该怎么做。我试过使用IFNULL,但这仅适用于一列,而不是列数。使用 IF 语句给了我错误,因为您无法从 if 语句返回行。 我认为它给我的错误是Scalar subquery cannot have more than one column unless using SELECT AS STRUCT to build STRUCT values

我能想到但不知道如何实现的另一件事是在末尾添加一个UNION,只有在前面的部分没有返回任何内容时才会触发。或者将现有查询包装在 WITH句子查询中,如果没有返回任何内容,则打印一条消息,否则执行 SELECT * FROM sub_query

我想在结果为空表时仅显示一条消息,或者返回带有一些默认值的行。 我知道答案可能包含UNION 语句,因此不可能只显示一条消息。在这种情况下,我想改为显示默认行。对于上述示例查询,默认行如下所示:"No results found", NULL, NULL。 当查询返回一个非空表时,我希望它看起来与原始查询完全一样。所以不应该有任何添加列或更改结果的架构。

【问题讨论】:

【参考方案1】:

选项一

如果没有为 your_query 返回结果,下面显示全为空的行

#standardSQL
WITH your_query AS ( ... )
SELECT * FROM your_query 
UNION ALL 
SELECT your_query.* REPLACE ("No results found" AS result)
FROM (SELECT 1) 
LEFT JOIN your_query ON FALSE
WHERE NOT EXISTS (SELECT 1 FROM your_query)  

Row result              number  message  
1   No results found    null    null     

选项 2

如果您事先知道输出模式 - 下面返回默认行(假设 number 的默认值为 0,message 的默认值为“无”

#standardSQL
WITH your_query AS ( ... )
SELECT * FROM your_query 
UNION ALL 
SELECT "No results found", 0, "none" FROM (SELECT 1) 
LEFT JOIN your_query ON FALSE
WHERE NOT EXISTS (SELECT 1 FROM your_query)

Row result              number  message  
1   No results found    0       none     

【讨论】:

我也赞成您的回答,因为它完全符合我的要求。请注意,您应该更新第二个查询,以便 select 语句读取类似于 "result", 0, "none"(您缺少一个字符串作为选择的第一个值) 你是对的。我只是不确定你是否需要那个“结果”字段。不知何故,我认为这是额外的 - 但如果出于某种原因你需要它 - 好的 :o) 没有它,查询将无法运行,因为列号不匹配 明白了——我在你原来的查询中引用了"query result" AS result——你为什么需要它? 哦,我明白了。这并不是真正需要的。我只是想在select 中添加一些东西,这样它就不仅仅是query1.* 【参考方案2】:

您将使用union all。像这样的:

with t as (
      . . . <all your query stuff here>
     )
select cast(NULL as string) as msg, t.*
from t
union all
select msg, t.*  -- all the `t` columns will be `NULL`
from (select 'No rows returned' as msg) left join
     t
     on 1 = 0  -- always false
where not exists (select 1 from t);

注意并发症。查询返回一组具有固定名称的固定列。此版本在数据的开头返回一个额外的列来包含消息。为了获取所有其余列,使用了left join,但on 子句始终为假。

【讨论】:

我赞成您的帖子,因为它回答了我的问题。你能想出一种不引入新列的方法吗? @alamoot 。 . .您可以将字符串放入任何现有的字符串列,但您的问题并没有真正解释结果集应该是什么样子。 好点,我在问题的末尾添加了一段描述结果的预期行为

以上是关于如果查询结果在 BigQuery 中没有记录,则显示默认值的主要内容,如果未能解决你的问题,请参考以下文章

Google Bigquery 查询记录数据 - 专利

Google Bigquery Legacy SQL - 如果没有返回结果,如何返回 null 或零?

BigQuery - 删除重复记录有时需要很长时间

为啥我的 bigquery sql 没有返回任何结果?

如何在 BigQuery 中透视表

BigQuery 未准确返回结果