Snowflake cloud data platform 雪花-返回两个数组之间不同(不相似)的值

Snowflake cloud data platform 雪花-返回两个数组之间不同(不相似)的值,snowflake-cloud-data-platform,Snowflake Cloud Data Platform,在查看了Snowflake文档之后,我找到了名为array_intersectionarray_1、array_2的函数,它将返回两个数组之间的公共值,但我需要使用任何一个数组中都不存在的值来显示数组 例1: 假设我的表中有以下两个数组 array_1 = ['a', 'b', 'c', 'd', 'e'] array_2 = ['a', 'f', 'c', 'g', 'e'] array_1 = ['u', 'v', 'w', 'x', 'y'] array_2 = ['u', 'v', '

在查看了Snowflake文档之后,我找到了名为array_intersectionarray_1、array_2的函数,它将返回两个数组之间的公共值,但我需要使用任何一个数组中都不存在的值来显示数组

例1:

假设我的表中有以下两个数组

array_1 = ['a', 'b', 'c', 'd', 'e']
array_2 = ['a', 'f', 'c', 'g', 'e']
array_1 = ['u', 'v', 'w', 'x', 'y']
array_2 = ['u', 'v', 'i', 'x', 'k']
我的问题是:

select
  array_intersection(array_1, array_2)
from myTable
select
  array_intersection(array_1, array_2)
from myTable
电流输出:

['a', 'c', 'e']
['u', 'v', 'x']
但我希望输出为:

['f', 'g']
['w', 'y', 'i', 'k']
例2:

假设我的表中有以下两个数组

array_1 = ['a', 'b', 'c', 'd', 'e']
array_2 = ['a', 'f', 'c', 'g', 'e']
array_1 = ['u', 'v', 'w', 'x', 'y']
array_2 = ['u', 'v', 'i', 'x', 'k']
我的问题是:

select
  array_intersection(array_1, array_2)
from myTable
select
  array_intersection(array_1, array_2)
from myTable
电流输出:

['a', 'c', 'e']
['u', 'v', 'x']
但我希望输出为:

['f', 'g']
['w', 'y', 'i', 'k']
如何在雪花中做到这一点?有什么建议吗

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]

这个问题中的集合运算就是物理学家所说的a。 在这种情况下,SQL hammer可能无法最佳地处理数组螺钉

一件事是让一个独立的查询处理一个基本情况,另一件完全不同的事是创建一个可维护的现实生活查询,该查询还包含其他复杂性

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);

根据上面的预期输出语句,您似乎希望第二个数组中的值不在第一个数组中?不过,我认为这不是你在介绍中所说的。你能澄清一下想要的结果吗?@MikeWalton我的意思是,我想要一个最终数组,它包含两个数组中都不存在的所有值。让我知道如果你仍然没有得到它,我可以在这里举个例子。公平的说,我只是在SF中有很多坏运气,随着事情变得复杂,它在过去随机爆炸,所以我只是推出比需要的CTE的时间更长。啊,但是如果有多行对,你的代码将失败,这就是为什么我要包含seq。问题中没有分析多行的要求,但我明白你的意思。但是,有没有理由不使用在使用“展平”时自动显示的“序列”字段?老实说,我没想到。。但考虑到它不是无间隙的,并且您正在独立地扩展A1和A2,您无法确定它们以相同的顺序扩展,因此没有行的通用框架。我喜欢这个答案,因为在创建一个包含100万行的表之后,我的sql耗时18秒,Hans耗时6秒。@SimeonPrilger我首先要的是sql解决方案,但后来我看到了你的,我想我再也做不到比这更好的了。但是,最精简的SQL仍然是一个怪物。最新的JavaScript在数组和对象方面确实比SQL有显著的优势,这一点并不令人惊讶,因为它是该语言的核心。感谢您分享计时信息。出于速度原因,我倾向于避免使用js创建或替换临时表myTable AS,循环为SELECT SEQ8 AS seq,5+absrandom%5 AS len from TABLEGONATOR ROWCOUNT=>1000000,行集为SELECT row_NUMBEROVERDER by true AS rn from table GENTORROWCOUNT=>10,字符为SELECT l.seq,l.len,r.rn,CHARUNIFORM65,90,随机为cha,CHARUNIFORM65,90,random+1作为循环中的chb l连接r.rn上的行集r,出于同样的原因,我也倾向于避免使用非SQL构造-我是数据仓库专业人员,不是应用程序程序员,所以这很自然:O。但我想在这种情况下,js字节码编译器可以将紧凑的表示法转换为某种效率的代码,甚至包括函数调用开销。。。