雪花 - return 两个数组之间的不同(不相似)值
Snowflake - return different (not similar) values between two arrays
查看 Snowflake 文档后,我发现名为 array_intersection(array_1, array_2)
的函数将 return 两个数组之间的公共值,但我需要显示数组中任何一个数组中都不存在的值.
示例 1:
假设我的 table
中有以下两个数组
array_1 = ['a', 'b', 'c', 'd', 'e']
array_2 = ['a', 'f', 'c', 'g', 'e']
我的查询:
select
array_intersection(array_1, array_2)
from myTable
当前输出:
['a', 'c', 'e']
但我希望输出为:
['f', 'g']
示例 2:
假设我的 table
中有以下两个数组
array_1 = ['u', 'v', 'w', 'x', 'y']
array_2 = ['u', 'v', 'i', 'x', 'k']
我的查询:
select
array_intersection(array_1, array_2)
from myTable
当前输出:
['u', 'v', 'x']
但我希望输出为:
['w', 'y', 'i', 'k']
如何在 Snowflake 中完成此操作?有什么建议吗?
with myTable as (
select array_construct('a', 'b', 'c', 'd', 'e') as a1
,array_construct('a', 'f', 'c', 'g', 'e') as a2
)
select a1, a2, array_intersection(a1, a2)
from myTable;
表明我们正在处理相同的数据。
with myTable as (
SELECT array_construct('a', 'b', 'c', 'd', 'e') as a1
,array_construct('a', 'f', 'c', 'g', 'e') as a2
), seq_myTable as (
SELECT seq8() as seq
,t.*
from myTable t
), expanded_a1 as (
select a.seq
,f.value as val
from seq_myTable a,
lateral flatten(input => a.a1) f
), expanded_a2 as (
select a.seq
,f.value as val
from seq_myTable a,
lateral flatten(input => a.a2) f
)
select coalesce(a.seq,b.seq) as seq, array_agg(coalesce(a.val,b.val)) as vals
from expanded_a1 a
full outer join expanded_a2 b
on a.seq = b.seq and a.val = b.val
where (a.seq is null OR b.seq is null)
group by 1;
这给出了答案,但它们没有排序,为此你需要:
with myTable as (
SELECT array_construct('a', 'b', 'c', 'd', 'e') as a1
,array_construct('a', 'f', 'c', 'g', 'e') as a2
), seq_myTable as (
SELECT seq8() as seq
,t.*
from myTable t
), expanded_a1 as (
select a.seq
,f.value as val
from seq_myTable a,
lateral flatten(input => a.a1) f
), expanded_a2 as (
select a.seq
,f.value as val
from seq_myTable a,
lateral flatten(input => a.a2) f
)
select array_agg(val) WITHIN GROUP ( order by val) as vals
from (
select coalesce(a.seq,b.seq) as seq, coalesce(a.val,b.val) as val
from expanded_a1 a
full outer join expanded_a2 b
on a.seq = b.seq and a.val = b.val
where (a.seq is null OR b.seq is null)
)
group by seq;
给出输出[ "b", "d", "f", "g" ]
这道题中的集合运算就是数学家所说的disjunctive union。
在这种情况下,SQL 锤子可能无法最佳处理 ARRAY 螺钉。
一件事是让一个孤立的查询与准系统案例一起工作,另一件事是创建一个可维护的现实生活中的查询,其中还包含其他复杂性。
JavaScript 是处理集合计算的理想选择,非常适合此任务:
CREATE OR REPLACE FUNCTION ARRAY_DISJUNCTIVE_UNION(A1 ARRAY, A2 ARRAY)
RETURNS ARRAY LANGUAGE JAVASCRIPT AS
'return [...A1.filter(e => !A2.includes(e)),...A2.filter(e => !A1.includes(e))]';
我不确定您是否需要像其他答案那样的序列。这工作得非常干净:
with myTable as (
select array_construct('a', 'b', 'c', 'd', 'e') as a1
,array_construct('a', 'f', 'c', 'g', 'e') as a2
)
SELECT array_agg(coalesce(a1.value,a2.value)) WITHIN GROUP (ORDER BY coalesce(a1.value,a2.value)) as newarray
FROM (
SELECT *
FROM myTable,
lateral flatten(input => a1) a1
) a1
FULL OUTER JOIN (
SELECT *
FROM myTable,
lateral flatten(input => a2) a2
) a2
ON a1.value::varchar = a2.value::varchar
WHERE a1.value IS NULL
OR a2.value IS NULL
;
您可以使用横向展平将数组转换为结果集,然后使用 SQL 集合操作比较元素,然后将结果转换回数组。
CTE(WITH 子句)的想法允许您在一个语句中完成所有这些。
create or replace table arrays as (select split('1,2,3',',') a, split('4,9,1,3',',') b); //some test data
with a_elements as
(select value from arrays,
lateral flatten(input => arrays.a) f ) // array to result set
, b_elements as
(select value from arrays,
lateral flatten(input => arrays.b) f )
select array_agg(value) // reassemble the array
from (select * from a_elements minus select * from b_elements);
查看 Snowflake 文档后,我发现名为 array_intersection(array_1, array_2)
的函数将 return 两个数组之间的公共值,但我需要显示数组中任何一个数组中都不存在的值.
示例 1:
假设我的 table
中有以下两个数组array_1 = ['a', 'b', 'c', 'd', 'e']
array_2 = ['a', 'f', 'c', 'g', 'e']
我的查询:
select
array_intersection(array_1, array_2)
from myTable
当前输出:
['a', 'c', 'e']
但我希望输出为:
['f', 'g']
示例 2:
假设我的 table
中有以下两个数组array_1 = ['u', 'v', 'w', 'x', 'y']
array_2 = ['u', 'v', 'i', 'x', 'k']
我的查询:
select
array_intersection(array_1, array_2)
from myTable
当前输出:
['u', 'v', 'x']
但我希望输出为:
['w', 'y', 'i', 'k']
如何在 Snowflake 中完成此操作?有什么建议吗?
with myTable as (
select array_construct('a', 'b', 'c', 'd', 'e') as a1
,array_construct('a', 'f', 'c', 'g', 'e') as a2
)
select a1, a2, array_intersection(a1, a2)
from myTable;
表明我们正在处理相同的数据。
with myTable as (
SELECT array_construct('a', 'b', 'c', 'd', 'e') as a1
,array_construct('a', 'f', 'c', 'g', 'e') as a2
), seq_myTable as (
SELECT seq8() as seq
,t.*
from myTable t
), expanded_a1 as (
select a.seq
,f.value as val
from seq_myTable a,
lateral flatten(input => a.a1) f
), expanded_a2 as (
select a.seq
,f.value as val
from seq_myTable a,
lateral flatten(input => a.a2) f
)
select coalesce(a.seq,b.seq) as seq, array_agg(coalesce(a.val,b.val)) as vals
from expanded_a1 a
full outer join expanded_a2 b
on a.seq = b.seq and a.val = b.val
where (a.seq is null OR b.seq is null)
group by 1;
这给出了答案,但它们没有排序,为此你需要:
with myTable as (
SELECT array_construct('a', 'b', 'c', 'd', 'e') as a1
,array_construct('a', 'f', 'c', 'g', 'e') as a2
), seq_myTable as (
SELECT seq8() as seq
,t.*
from myTable t
), expanded_a1 as (
select a.seq
,f.value as val
from seq_myTable a,
lateral flatten(input => a.a1) f
), expanded_a2 as (
select a.seq
,f.value as val
from seq_myTable a,
lateral flatten(input => a.a2) f
)
select array_agg(val) WITHIN GROUP ( order by val) as vals
from (
select coalesce(a.seq,b.seq) as seq, coalesce(a.val,b.val) as val
from expanded_a1 a
full outer join expanded_a2 b
on a.seq = b.seq and a.val = b.val
where (a.seq is null OR b.seq is null)
)
group by seq;
给出输出[ "b", "d", "f", "g" ]
这道题中的集合运算就是数学家所说的disjunctive union。
在这种情况下,SQL 锤子可能无法最佳处理 ARRAY 螺钉。
一件事是让一个孤立的查询与准系统案例一起工作,另一件事是创建一个可维护的现实生活中的查询,其中还包含其他复杂性。
JavaScript 是处理集合计算的理想选择,非常适合此任务:
CREATE OR REPLACE FUNCTION ARRAY_DISJUNCTIVE_UNION(A1 ARRAY, A2 ARRAY)
RETURNS ARRAY LANGUAGE JAVASCRIPT AS
'return [...A1.filter(e => !A2.includes(e)),...A2.filter(e => !A1.includes(e))]';
我不确定您是否需要像其他答案那样的序列。这工作得非常干净:
with myTable as (
select array_construct('a', 'b', 'c', 'd', 'e') as a1
,array_construct('a', 'f', 'c', 'g', 'e') as a2
)
SELECT array_agg(coalesce(a1.value,a2.value)) WITHIN GROUP (ORDER BY coalesce(a1.value,a2.value)) as newarray
FROM (
SELECT *
FROM myTable,
lateral flatten(input => a1) a1
) a1
FULL OUTER JOIN (
SELECT *
FROM myTable,
lateral flatten(input => a2) a2
) a2
ON a1.value::varchar = a2.value::varchar
WHERE a1.value IS NULL
OR a2.value IS NULL
;
您可以使用横向展平将数组转换为结果集,然后使用 SQL 集合操作比较元素,然后将结果转换回数组。
CTE(WITH 子句)的想法允许您在一个语句中完成所有这些。
create or replace table arrays as (select split('1,2,3',',') a, split('4,9,1,3',',') b); //some test data
with a_elements as
(select value from arrays,
lateral flatten(input => arrays.a) f ) // array to result set
, b_elements as
(select value from arrays,
lateral flatten(input => arrays.b) f )
select array_agg(value) // reassemble the array
from (select * from a_elements minus select * from b_elements);