在 CLI 上使用 bq 从 BigQuery 标准 SQL 连接表中打印出漂亮的值表?

Posted

技术标签:

【中文标题】在 CLI 上使用 bq 从 BigQuery 标准 SQL 连接表中打印出漂亮的值表?【英文标题】:Pretty print value table from BigQuery Standard SQL joined tables using bq on CLI? 【发布时间】:2020-02-12 14:21:53 【问题描述】:

有没有办法使用标准 SQL 使用bq 命令行工具来漂亮地格式化 Big Query“值表”结果集?这可以在标准 SQL 的 BigQuery 控制台中按预期工作,但在 bq 中则不行。我找不到方便的解决方法。使用 Legacy SQL 时,它也能按预期工作。

我的用例:我正在探索 BigQuery 中包含大量列的表。 BigQuery 中的匿名查询要求所选列具有唯一名称,否则您会收到消息“不支持结果中的重复列名称。发现重复:...”。当我只是在探索数据时,这是一个非常严格的要求。幸运的是,BigQuery Web 控制台中有一种方法可以解决此问题,方法是在选择表达式中使用值表...

with
left_side as
(
select 1 as id, 'hello' as col1 union all 
select 2 as id, 'there' as col1
)
,right_side as
(
select 1 as id, 'hello' as col1 union all 
select 2 as id, 'world' as col1
)
select a, b
  from left_side a
       join
       right_side b
          on a.id = b.id

...这会产生以下表格结果集,其中列自动枚举,非常好...

但是,在命令行上将完全相同的查询传递给bq,如下所示(为方便起见,通过此处的文档)。通常,我将查询放在一个文件中并将其重定向到bq,例如bq query --use_legacy_sql=false < bq_test4.sql

bq query --use_legacy_sql=false <<BQ_TEST
with
left_side as
(
select 1 as id, 'hello' as col1 union all 
select 2 as id, 'there' as col1
)
,right_side as
(
select 1 as id, 'hello' as col1 union all 
select 2 as id, 'world' as col1
)
select a, b
  from left_side a
       join
       right_side b
          on a.id = b.id
BQ_TEST

...无论传递给bq...的任何--format 选项如何,都会产生相同的基本结果集...

+---------------------------+---------------------------+
|             a             |             b             |
+---------------------------+---------------------------+
| "id":"1","col1":"hello" | "id":"1","col1":"hello" |
| "id":"2","col1":"there" | "id":"2","col1":"world" |
+---------------------------+---------------------------+

这样的结果集对我没有帮助。

好的,我可以将 json 转换为表格结果集...

with
left_side as
(
select 1 as id, 'hello' as col1 union all 
select 2 as id, 'there' as col1
)
,right_side as
(
select 1 as id, 'hello' as col1 union all 
select 2 as id, 'world' as col1
)
select json_extract_scalar(to_json_string(a), "$['id']") as `a_id`
      ,json_extract_scalar(to_json_string(a), "$['col1']") as `a_col1`
      ,json_extract_scalar(to_json_string(b), "$['id']") as `b_id`
      ,json_extract_scalar(to_json_string(b), "$['col1']") as `b_col1`
  from left_side a
       join
       right_side b
          on a.id = b.id

...导致旧版 SQL 将产生的结果...

+------+--------+------+--------+
| a_id | a_col1 | b_id | b_col1 |
+------+--------+------+--------+
| 1    | hello  | 1    | hello  |
| 2    | there  | 2    | world  |
+------+--------+------+--------+

必须枚举列违背了我用例的意图。

在使用标准 SQL 时,有什么方法可以避免在我加入之前或之后枚举列?

【问题讨论】:

【参考方案1】:

仍然需要一些输入 - 但不那么冗长的版本

#standardSQL
WITH left_side AS (
  SELECT 1 AS id, 'hello' AS col1 UNION ALL 
  SELECT 2 AS id, 'there' AS col1
), right_side AS (
  SELECT 1 AS id, 'hello' AS col1 UNION ALL 
  SELECT 2 AS id, 'world' AS col1
)
SELECT *
FROM (SELECT NULL a_id, NULL a_col1 UNION ALL SELECT * FROM left_side) a
JOIN (SELECT NULL b_id, NULL b_col1 UNION ALL SELECT * FROM right_side) b
ON a_id = b_id

结果

Row a_id    a_col1  b_id    b_col1   
1   1       hello   1       hello    
2   2       there   2       world    

所以在bq中会如下...

+------+--------+------+--------+
| a_id | a_col1 | b_id | b_col1 |
+------+--------+------+--------+
| 1    | hello  | 1    | hello  |
| 2    | there  | 2    | world  |
+------+--------+------+--------+

【讨论】:

是的,这是一个很好的解决方法 - 谢谢 - 我想我可以自动生成列列表,但我确实想避免这种情况。你知道这是否被认为是 bq 中的一个已知问题?我的另一种选择是在 python 中编写我自己的 bq 并在那里处理 json 转换。 1) 是的 - 我看不到避免生成(手动或通过代码)列列表的方法。 2) 我不确定 - 但很可能这不被视为标准 SQL 的问题 - 但您可以发布功能请求,以便他们考虑:o) 是否根据您的建议自动生成列列表 re NULL 通过从 vim 到查询 information_schema 将完全限定的表名和别名作为参数传递。效果很好,但很冗长,并且涉及修改连接条件。还在 python 中实现以检测 [0,0] 中的 dict(稍后可以返工以检查所有 cols 上是否存在 dict)并迭代以重铸为 DataFrame。必须更好,更通用,并且意味着我不必弄乱我的 SQL。感谢您的建议。我可能会看看记录一个功能请求......这将是 bq 命令的一个有用选项。

以上是关于在 CLI 上使用 bq 从 BigQuery 标准 SQL 连接表中打印出漂亮的值表?的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从 Redshift 迁移到 BigQuery

如何从 BigQuery 作为流读取

在 BigQuery 上上传和导入数据时从 bq 工具获取错误 - “后端错误”

BigQuery 从 bq 命令行工具加载数据 - 如何跳过标题行

使用 bq 将数据加载到 BigQuery 的自定义日期格式?

从表中读取 BigQuery 数值数据类型