在 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 连接表中打印出漂亮的值表?的主要内容,如果未能解决你的问题,请参考以下文章
在 BigQuery 上上传和导入数据时从 bq 工具获取错误 - “后端错误”
BigQuery 从 bq 命令行工具加载数据 - 如何跳过标题行