英文:
Is value in array column in Snowflake?
问题
我需要生成一个布尔列,判断一个值(例如 1
)是否在数组(例如 [1,2]
)中,针对表中的每一行。我的问题是:这样做的最佳方式是什么?
据我了解,在Snowflake中,ARRAY
中的所有元素都是VARIANT
类型。这展示了我正在使用的选项。我个人正在尝试弄清楚如何判断NUMBER
列中的值是否是ARRAY
列的元素。
示例
WITH example_cte AS (
SELECT
CAST(1 AS VARIANT) one_as_variant,
CAST('1' AS VARIANT) string_one_as_variant,
CAST(CAST(1 AS VARCHAR) AS VARIANT) as one_as_varchar_then_variant,
[ '2', '1' ] AS my_array
)
SELECT
ARRAY_CONTAINS(one_as_variant, my_array) as one_as_variant_is_in_array, -- evaluates as FALSE
ARRAY_CONTAINS(string_one_as_variant, my_array) as string_one_as_variant_is_in_array, -- evaluates as TRUE
ARRAY_CONTAINS(one_as_varchar_then_variant, my_array) as one_as_varchar_then_variant_is_in_array -- evaluates as TRUE
FROM
example_cte;
英文:
I need to generate a boolean column that evaluates whether a value (e.g. 1
) is in an array (e.g. [1,2]
) for each row of my table. My question is: what is the best way to do this?
As I understand, all elements of an ARRAY
in Snowflake are of type VARIANT
. These demonstrate the options I'm working with. I'm personally trying to figure out how to see if the value in a NUMBER
column is an element of the ARRAY
column.
Example
WITH example_cte AS (
SELECT
CAST(1 AS VARIANT) one_as_variant,
CAST('1' AS VARIANT) string_one_as_variant,
CAST(CAST(1 AS VARCHAR) AS VARIANT) as one_as_varchar_then_variant,
[ '2', '1' ] AS my_array
)
SELECT
ARRAY_CONTAINS(one_as_variant, my_array) as one_as_variant_is_in_array, -- evaluates as FALSE
ARRAY_CONTAINS(string_one_as_variant, my_array) as string_one_as_variant_is_in_array, -- evaluates as TRUE
ARRAY_CONTAINS(one_as_varchar_then_variant, my_array) as one_as_varchar_then_variant_is_in_array -- evaluates as TRUE
FROM
example_cte;
答案1
得分: 1
所以变体"have a type",因此字符串不是数字,如果尝试创建一个包含字符串的数字数组,则会失败,但数字数组则不会:
V1_N | V1_S | V1_N_S | A1 | A2 | A1_CONTAINS_V1_N | A1_CONTAINS_V1_S | A1_CONTAINS_V1_N_S | A2_CONTAINS_V1_N | A2_CONTAINS_V1_S | A2_CONTAINS_V1_N_S |
---|---|---|---|---|---|---|---|---|---|---|
1 | "1" | "1" | [ "2", "1" ] | [ 2, 1 ] | FALSE | TRUE | TRUE | TRUE | FALSE | FALSE |
所以如果我们问类型是什么:
col | value | type |
---|---|---|
V1_N | 1 | INTEGER |
V1_S | "1" | VARCHAR |
V1_N_S | "1" | VARCHAR |
A1 | [ "2", "1" ] | VARCHAR |
A2 | [ 2, 1 ] | INTEGER |
那么如何解决这个问题?
如果您的数组具有混合类型,您将不得不重建它们,但然后您就可以知道将值转换为什么类型。
或者,如果您知道数组的类型始终是字符串,就像您的示例一样,您可以只转换这些值:
V1_N | V1_S | V1_N_S | A1 | C_V1_N | C_V1_S | C_V1_N_S |
---|---|---|---|---|---|---|
1 | "1" | "1" | [ "2", "1" ] | TRUE | TRUE | TRUE |
英文:
So the variant "have a type", and thus string are not number, and making an array of numbers, fails for the strings, but passes for the numbers:
SELECT
1::VARIANT as v1_n,
'1'::VARIANT as v1_s,
1::VARCHAR::VARIANT as v1_n_s,
array_construct('2', '1') as a1,
array_construct(2, 1) as a2,
ARRAY_CONTAINS(v1_n, a1) as a1_contains_v1_n,
ARRAY_CONTAINS(v1_s, a1) as a1_contains_v1_s,
ARRAY_CONTAINS(v1_n_s, a1) as a1_contains_v1_n_s,
ARRAY_CONTAINS(v1_n, a2) as a2_contains_v1_n,
ARRAY_CONTAINS(v1_s, a2) as a2_contains_v1_s,
ARRAY_CONTAINS(v1_n_s, a2) as a2_contains_v1_n_s
V1_N | V1_S | V1_N_S | A1 | A2 | A1_CONTAINS_V1_N | A1_CONTAINS_V1_S | A1_CONTAINS_V1_N_S | A2_CONTAINS_V1_N | A2_CONTAINS_V1_S | A2_CONTAINS_V1_N_S |
---|---|---|---|---|---|---|---|---|---|---|
1 | "1" | "1" | [ "2", "1" ] | [ 2, 1 ] | FALSE | TRUE | TRUE | TRUE | FALSE | FALSE |
so then if we ask what the types are:
SELECT
1::VARIANT as v1_n,
TYPEOF(v1_n) as t_v1_n,
'1'::VARIANT as v1_s,
TYPEOF(v1_s) as t_v1_s,
1::VARCHAR::VARIANT as v1_n_s,
TYPEOF(v1_n_s) as t_v1_n_s,
array_construct('2', '1') as a1,
TYPEOF(a1[0]) as t_a1_0,
array_construct(2, 1) as a2,
TYPEOF(a2[0]) as t_a2_0
col | value | type |
---|---|---|
V1_N | 1 | INTEGER |
V1_S | "1" | VARCHAR |
V1_N_S | "1" | VARCHAR |
A1 | [ "2", "1" ] | VARCHAR |
A2 | [ 2, 1 ] | INTEGER |
so how to get around this?
If you array have mixed types, you will have to rebuild them, but then you can know what to cast your values to.
OR if you know the type of array is always strings, like in your example, you can just cast the values:
SELECT
1::VARIANT as v1_n,
'1'::VARIANT as v1_s,
1::VARCHAR::VARIANT as v1_n_s,
array_construct('2', '1') as a1,
array_contains(v1_n::text::variant, a1) as c_v1_n,
array_contains(v1_s::text::variant, a1) as c_v1_s,
array_contains(v1_n_s::text::variant, a1) as c_v1_n_s
V1_N | V1_S | V1_N_S | A1 | C_V1_N | C_V1_S | C_V1_N_S |
---|---|---|---|---|---|---|
1 | "1" | "1" | [ "2", "1" ] | TRUE | TRUE | TRUE |
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论