Big Query SQL 连接或链接管道字符串或字符串数组中的值
Big Query SQL concatenating or linking values in piped strings or arrays of strings
我在一个大 BQ 中有两个字段 table。这两个字段都是字符串。两个字符串都被格式化为表示由竖线分隔的几个值,每个字符串中的值数量相同。我需要将第一组中的每个值与第二组中的每个值相关联。例如:
id names nums
x "a|b|c" "3|9|5"
y "d" "1"
z "e|f" "4|7"
我需要得出这样的结果:
x,a,3
x,b,9
x,c,5
y,d,1
z,e,4
z,f,7
第二个输入字符串是一个数字序列,但我不介意它是数字还是字符串(我会弄清楚转换)。
似乎很明显我需要在某些时候使用 split() 可以将字符串转换为数组,但是我怎样才能从左到右而不是按长度连接数组?
我知道我只能在索引相等的情况下使用带有索引和 select 的双重 unnest,但是我不想使用这种方法,因为它使已经很大的输入 table 变得巨大(在 select使用相等的索引)。
感谢您的任何想法!
下面是一个生成一系列下标并使用数组提取值的方法:
select id, split(names, '|')[safe_ordinal(n)] as names,
split(nums, '|')[safe_ordinal(n)] as nums
from (select 'x' as id, 'a|b|c' as names, '3|9|5' as nums union all
select 'y', 'd', '1' union all
select 'z', 'e|f', '4|7'
) t cross join
unnest(generate_array(1, array_length(split(names, '|')))) as n;
这使用 names
的长度来确定有多少个值。
BigQuery 标准的替代选项 SQL
#standardSQL
SELECT id, name, num
FROM `project.dataset.table`,
UNNEST(SPLIT(names, '|')) name WITH OFFSET
JOIN UNNEST(SPLIT(nums, '|')) num WITH OFFSET
USING(OFFSET)
如果适用于您问题中的示例数据,如下例所示
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'x' id, 'a|b|c' names, '3|9|5' nums UNION ALL
SELECT 'y', 'd', '1' UNION ALL
SELECT 'z', 'e|f', '4|7'
)
SELECT id, name, num
FROM `project.dataset.table`,
UNNEST(SPLIT(names, '|')) name WITH OFFSET
JOIN UNNEST(SPLIT(nums, '|')) num WITH OFFSET
USING(OFFSET)
结果是
Row id name num
1 x a 3
2 x b 9
3 x c 5
4 y d 1
5 z e 4
6 z f 7
以上内容可以重构为使用 UDF,因此主查询变得简单易读 - 如以下示例所示
#standardSQL
CREATE TEMP FUNCTION xxx(arr1 ANY TYPE, arr2 ANY TYPE)
RETURNS ARRAY<STRUCT<name STRING, num STRING>> AS (
ARRAY(
SELECT AS STRUCT el1, el2
FROM UNNEST(SPLIT(arr1, '|')) el1 WITH OFFSET
JOIN UNNEST(SPLIT(arr2, '|')) el2 WITH OFFSET
USING(OFFSET)
));
SELECT id, x.*
FROM `project.dataset.table`, UNNEST(xxx(names, nums)) x
显然具有相同的输出
我在一个大 BQ 中有两个字段 table。这两个字段都是字符串。两个字符串都被格式化为表示由竖线分隔的几个值,每个字符串中的值数量相同。我需要将第一组中的每个值与第二组中的每个值相关联。例如:
id names nums
x "a|b|c" "3|9|5"
y "d" "1"
z "e|f" "4|7"
我需要得出这样的结果:
x,a,3
x,b,9
x,c,5
y,d,1
z,e,4
z,f,7
第二个输入字符串是一个数字序列,但我不介意它是数字还是字符串(我会弄清楚转换)。
似乎很明显我需要在某些时候使用 split() 可以将字符串转换为数组,但是我怎样才能从左到右而不是按长度连接数组?
我知道我只能在索引相等的情况下使用带有索引和 select 的双重 unnest,但是我不想使用这种方法,因为它使已经很大的输入 table 变得巨大(在 select使用相等的索引)。
感谢您的任何想法!
下面是一个生成一系列下标并使用数组提取值的方法:
select id, split(names, '|')[safe_ordinal(n)] as names,
split(nums, '|')[safe_ordinal(n)] as nums
from (select 'x' as id, 'a|b|c' as names, '3|9|5' as nums union all
select 'y', 'd', '1' union all
select 'z', 'e|f', '4|7'
) t cross join
unnest(generate_array(1, array_length(split(names, '|')))) as n;
这使用 names
的长度来确定有多少个值。
BigQuery 标准的替代选项 SQL
#standardSQL
SELECT id, name, num
FROM `project.dataset.table`,
UNNEST(SPLIT(names, '|')) name WITH OFFSET
JOIN UNNEST(SPLIT(nums, '|')) num WITH OFFSET
USING(OFFSET)
如果适用于您问题中的示例数据,如下例所示
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'x' id, 'a|b|c' names, '3|9|5' nums UNION ALL
SELECT 'y', 'd', '1' UNION ALL
SELECT 'z', 'e|f', '4|7'
)
SELECT id, name, num
FROM `project.dataset.table`,
UNNEST(SPLIT(names, '|')) name WITH OFFSET
JOIN UNNEST(SPLIT(nums, '|')) num WITH OFFSET
USING(OFFSET)
结果是
Row id name num
1 x a 3
2 x b 9
3 x c 5
4 y d 1
5 z e 4
6 z f 7
以上内容可以重构为使用 UDF,因此主查询变得简单易读 - 如以下示例所示
#standardSQL
CREATE TEMP FUNCTION xxx(arr1 ANY TYPE, arr2 ANY TYPE)
RETURNS ARRAY<STRUCT<name STRING, num STRING>> AS (
ARRAY(
SELECT AS STRUCT el1, el2
FROM UNNEST(SPLIT(arr1, '|')) el1 WITH OFFSET
JOIN UNNEST(SPLIT(arr2, '|')) el2 WITH OFFSET
USING(OFFSET)
));
SELECT id, x.*
FROM `project.dataset.table`, UNNEST(xxx(names, nums)) x
显然具有相同的输出