Google BigQuery - 从选择语句执行动态生成的查询
Posted
技术标签:
【中文标题】Google BigQuery - 从选择语句执行动态生成的查询【英文标题】:Google BigQuery - Execute dynamically generated queries from a select statement 【发布时间】:2018-07-17 23:27:13 【问题描述】:在 Google BigQuery 中有一个具有以下结构的巨大表(> 1 亿行):
name | departments
abc | 1,2,5,6
xyz | 4,5
pqr | 3,4,6
想要将数据转换成以下格式:
name | 1 | 2 | 3 | 4 | 5 | 6
abc | 1 | 1 | | | 1 | 1
xyz | | | | 1 | 1 |
pqr | | | 1 | 1 | | 1
截至目前,能够使用 CONCAT 和 REGEX_REPLACE 函数生成准备此格式数据集所需的查询:
SELECT ' insert into dataset.output ( name, ' +
CONCAT(
'_' , replace(departments,',',',_') )
+ ' ) values( \'' + name +'\','+ REGEXP_REPLACE(departments, "([^,\n]+)", "1") +')'
FROM (
select name, departments from dataset.input )
这会生成带有 100 M 插入查询的输出,这些查询可用于创建所需结构中的数据。
但是,下面是我的问题:
我们是否可以使用 Big Query SQL 直接执行此查询的输出(100 M 插入查询),或者我们需要一个一个地触发每个插入?
我相信没有办法旋转或转置具有多个逗号分隔值的列中的数据。对吗?
有没有更优化的方法可以使用 BigQuery SQL 实现这一点,而不是编写自定义 Java 代码?
谢谢。
【问题讨论】:
【参考方案1】:以下 BigQuery 标准 SQL 示例
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'abc' name, '1,2,5,6' departments UNION ALL
SELECT 'xyz', '4,5' UNION ALL
SELECT 'pqr', '3,4,6'
)
SELECT
name,
IF(departments LIKE '%1%', 1, 0) AS d1,
IF(departments LIKE '%2%', 1, 0) AS d2,
IF(departments LIKE '%3%', 1, 0) AS d3,
IF(departments LIKE '%4%', 1, 0) AS d4,
IF(departments LIKE '%5%', 1, 0) AS d5,
IF(departments LIKE '%6%', 1, 0) AS d6
FROM `project.dataset.table`
结果为
Row name d1 d2 d3 d4 d5 d6
1 abc 1 1 0 0 1 1
2 xyz 0 0 0 1 1 0
3 pqr 0 0 1 1 0 1
因此,您需要在目的地上方运行到您准备的任何新表
注意,以上假设您只有 6 个部门,最重要的是数字没有歧义,例如 1 与 10 不冲突 如果你确实有这种情况 - 你需要在下面进行转换
IF(departments LIKE '%2%', 1, 0) AS d2,
进入
IF(CONCAT(',', departments, ',') LIKE '%,2,%', 1, 0) AS d2 ...
当然,您可以只使用一个简单的 INSERT 语句
INSERT `project.dataset.new_table` (name, d1, d2, d3, d4, d5, d6)
SELECT
name,
IF(departments LIKE '%1%', 1, 0) AS d1,
IF(departments LIKE '%2%', 1, 0) AS d2,
IF(departments LIKE '%3%', 1, 0) AS d3,
IF(departments LIKE '%4%', 1, 0) AS d4,
IF(departments LIKE '%5%', 1, 0) AS d5,
IF(departments LIKE '%6%', 1, 0) AS d6
FROM `project.dataset.table`
所以,这一切的最后一点是: 而不是为原始表中的每一行生成 INSERT STATEMENT - 您应该生成简单的 SELECT 语句来“旋转”
“极端”最小化生成代码的更新
看一个例子:
#standardSQL
CREATE TEMP FUNCTION c(departments STRING, department INT64) AS (
IF(departments LIKE CONCAT('%',CAST(department AS STRING),'%'), 1, 0)
);
WITH `project.dataset.table` AS (
SELECT 'abc' name, '1,2,5,6' departments UNION ALL
SELECT 'xyz', '4,5' UNION ALL
SELECT 'pqr', '3,4,6'
), temp AS (
SELECT name, departments AS d
FROM `project.dataset.table`
)
SELECT
name,
c(d,1)d1,
c(d,2)d2,
c(d,3)d3,
c(d,4)d4,
c(d,5)d5,
c(d,6)d6
FROM temp
如您所见 - 现在您的 10000 行中的每一行都类似于 c(d,N)dN,
,最大长度为 c(d,10000)d10000,
,因此您有机会适应查询大小限制
【讨论】:
嗨,米哈伊尔,感谢您的及时回复。实际上,唯一部门 ID 的数量可以是 ~10000 。因此不确定我们是否可以在 JAVA 程序中动态生成此 SELECT 查询。对于如此大量的预期列,这种方法是否有任何限制? 您需要适应的列数和行大小有限制 据我们了解,Google BigQuery 最多支持 10000 列 我已经回答了一些关于动态生成数据透视查询的非常相似的问题——您应该在 SO 上进行搜索。只要你不超过限制 - 你应该是好的。注意:另一个限制是查询文本的大小。注意:10000 列绝对是非常极端的情况,听起来很可疑的设计 - 你可能想检查是否/为什么你甚至需要这样做 再次感谢米哈伊尔。如果有任何进一步的问题,将通过这些并回复。由于我们尝试服务的数据处理用例类型,我们需要这么多列。以上是关于Google BigQuery - 从选择语句执行动态生成的查询的主要内容,如果未能解决你的问题,请参考以下文章
从 Google BigQuery 中的选择中排除数组类型字段
Google BigQuery 从 Python 脚本执行 SQL 文件
从 Google BigQuery 创建熊猫数据框时如何执行 na_values