查询雪花中数组的子集

Posted

技术标签:

【中文标题】查询雪花中数组的子集【英文标题】:Query a subset of an array in snowflake 【发布时间】:2021-07-06 23:26:47 【问题描述】:

我正在尝试根据我的一个列中的数组元素在雪花中对 SQL 查询进行子集化,但不知道该怎么做。

例如,如果 column2 是一个看起来像这样的数组数据类型

SELECT column2
FROM table
LIMIT 7;

有输出:


Row column2
1 ["cats","dogs"]
2 ["horses","cows","cats"]
3 NULL
4 ["dogs","fish]
5 ["birds"]
6 ["cats"]
7 NULL

我想对数据进行子集化并运行一个查询,该查询将“猫”作为第 2 列中任何数组中的任何元素的任何行拉入 - 所以第 1、2 和 6 行 - 我将如何构造它查询?

使用这样的东西是行不通的:

SELECT column1, column2, column3
FROM Table
WHERE column2 = "cats" (or using an IN statement)

并导致错误消息为无效标识符“cats”,这是我所期望的,因为它位于数组中

任何见解将不胜感激!

【问题讨论】:

【参考方案1】:

你想要array_contains():

where array_contains('cats'::variant, column2)

【讨论】:

所以,当我在实际查询中执行此操作时,我得到SQL compilation error: line 6 at position 4 invalid argument types for function 'ARRAY_CONTAINS: (VARCHAR(9), ARRAY). 如果这有区别,则数组内的数据用双引号引起来。 array_contains 可以工作,但您需要注意类型,请参阅***.com/a/68278871/132438【参考方案2】:

ARRAY_CONTAINS() 有效,但你必须小心类型。

比如这个返回false:

select array_contains('2020-01-01'::date::variant
    , array_construct('2020-01-01', '2019-01-01'));

但这些都返回 true:

select array_contains('2020-01-01'::date::string::variant
    , array_construct('2020-01-01', '2019-01-01'));


select array_contains('2020-01-01'::date::variant
    , array_construct('2020-01-01'::date, '2019-01-01'));

在字符串的情况下,这个返回一个编译错误(如你所见):

select array_contains('cats'
    , array_construct('cats', 'dogs'));

-- SQL compilation error: error line 1 at position 7 Invalid argument types for function 'ARRAY_CONTAINS': (VARCHAR(4), ARRAY)

但是这个解决了它:

select array_contains('cats'::variant
    , array_construct('cats', 'dogs'));

【讨论】:

好的,有趣。那么::variant 表示数组中还有其他元素?我是否必须在声明array_construct('cats', 'dogs')) 中明确声明它们是什么?当不同的行具有包含“猫”以及["horses","cows","cats"] 或仅["cat"] 的不同元素集的数组时,这使得查询变得困难,或者就此而言,我实际上不知道哪些其他元素与猫有关的许多列。 抱歉,我的意思是“猫”的结尾带有一个“s”。我不打算用单数和复数来使单词不同,它们都应该是相同的和复数的。我很抱歉造成混乱。 我不确定这个问题是什么意思。我使用了array_construct,因为我没有像您已经拥有的带有数组的表。你试过where array_contains('cats'::variant, column2)吗? 最后一个问题。是否可以在包含“猫”的同时排除另一个元素,例如“马”?因此,创建一个包含第 1 行 ["cats","dogs"] 和第 6 行 ["cats"] 但不包括第 2 行的查询,因为您不希望任何行中包含“马”,即使“猫”是该数组的一部分? 让我们把它作为一个新问题来做吧 ;)【参考方案3】:

array_contains 可以让您回答您的具体问题,但是我认为了解如何将数组转换为看起来更像表格的东西可能会很有用。

如果您使用数组,雪花中的横向 flatten 函数绝对值得一试。

with cte as (
  select 'some other info_1' col_1 ,ARRAY_CONSTRUCT('cats','dogs') col_2  
union select 'some other info_2' col_1 ,ARRAY_CONSTRUCT('horses','cows','cats')
union select 'some other info_3' col_1 ,NULL
union select 'some other info_4' col_1 ,ARRAY_CONSTRUCT('dogs','fish')
union select 'some other info_5' col_1 ,ARRAY_CONSTRUCT('birds')
union select 'some other info_6' col_1 ,ARRAY_CONSTRUCT('cats')
union select 'some other info_7' col_1 ,NULL )

select col_1, animals.value from cte ,lateral flatten(col_2) animals 
where animals.value = 'cats';

【讨论】:

以上是关于查询雪花中数组的子集的主要内容,如果未能解决你的问题,请参考以下文章

将 MongoDB 查询转换为雪花

以数组为参数的雪花函数因不支持的子查询错误而失败

雪花不支持的子查询类型无法在 UDF 标量中评估

使基于雪花 Javascript 的过程查询更快

雪花中的查询超时问题

雪花警报长时间运行的查询