Presto 在聚合期间过滤数组
Presto filter an array during aggregation
我想根据与 id
关联的所有值来过滤聚合数组。值是字符串,可以是 all-x:y
、x:y
和空三种类型(这里 x
和 y
是值的任意子字符串)。
我有几个条件:
- 如果
id
有 x:y
那么结果应该包含 x:y
.
- 如果
id
总是 有 all-x:y
那么生成的聚合应该有 all-x:y
- 如果
id
有时 有 all-x:y
那么生成的聚合应该有 x:y
例如下面的
WITH
my_table(id, my_values) AS (
VALUES
(1, ['all-a','all-b']),
(2, ['all-c','b']),
(3, ['a','b','c']),
(1, ['all-a']),
(2, []),
(3, ['all-c']),
),
结果应该是:
(1, ['all-a','b']),
(2, ['c','b']),
(3, ['a','b','c']),
我为此工作了多个小时,但似乎不可行。
我想到了以下内容,但感觉它无法工作,因为我可以检查 <<IN ALL>>
:
中所有数组中是否存在 all-x
SELECT
id,
SET_UNION(
CASE
WHEN SPLIT_PART(my_table.values,'-',1) = 'all' THEN
CASE
WHEN <<my_table.values IN ALL>> THEN my_table.values
ELSE REPLACE(my_table.values,'all-')
END
ELSE my_table.values
END
) AS values
FROM my_table
GROUP BY 1
我需要检查特定 id
的所有数组 values
是否包含 all-x
,这就是我努力寻找解决方案的地方。
我想合作
经过几个小时的搜索,我开始相信这是不可行的。
任何帮助表示赞赏。感谢阅读。
这应该可以满足您的要求:
WITH my_table(id, my_values) AS (
VALUES
(1, array['all-a','all-b']),
(2, array['all-c','b']),
(3, array['a','b','c']),
(1, array['all-a']),
(2, array[]),
(3, array['all-c'])
),
with_group_counts AS (
SELECT *, count(*) OVER (PARTITION BY id) group_count -- to see if the number of all-X occurrences match the number of rows for a given id
FROM my_table
),
normalized AS (
SELECT
id,
if(
count(*) OVER (PARTITION BY id, value) = group_count AND starts_with(value, 'all-'), -- if its an all-X value and every original row for the given id contains it ...
value,
if(starts_with(value, 'all-'), substr(value, 5), value)) AS extracted
FROM with_group_counts CROSS JOIN UNNEST(with_group_counts.my_values) t(value)
)
SELECT id, array_agg(DISTINCT extracted)
FROM normalized
GROUP BY id
技巧是通过 with_group_counts
子查询中的 count(*) OVER (PARTITION BY id)
表达式计算原始 table 中每个 id 的总行数。然后我们可以使用该值来确定给定值是应该被视为 all-x
还是应该提取 x
。这是由以下表达式处理的:
if(
count(*) OVER (PARTITION BY id, value) = group_count AND starts_with(value, 'all-'),
value,
if(starts_with(value, 'all-'), substr(value, 5), value))
有关 Presto 中 window 函数的更多信息,请查看 documentation. You can find the documentation for UNNEST
here。
我想根据与 id
关联的所有值来过滤聚合数组。值是字符串,可以是 all-x:y
、x:y
和空三种类型(这里 x
和 y
是值的任意子字符串)。
我有几个条件:
- 如果
id
有x:y
那么结果应该包含x:y
. - 如果
id
总是 有all-x:y
那么生成的聚合应该有all-x:y
- 如果
id
有时 有all-x:y
那么生成的聚合应该有x:y
例如下面的
WITH
my_table(id, my_values) AS (
VALUES
(1, ['all-a','all-b']),
(2, ['all-c','b']),
(3, ['a','b','c']),
(1, ['all-a']),
(2, []),
(3, ['all-c']),
),
结果应该是:
(1, ['all-a','b']),
(2, ['c','b']),
(3, ['a','b','c']),
我为此工作了多个小时,但似乎不可行。
我想到了以下内容,但感觉它无法工作,因为我可以检查 <<IN ALL>>
:
all-x
SELECT
id,
SET_UNION(
CASE
WHEN SPLIT_PART(my_table.values,'-',1) = 'all' THEN
CASE
WHEN <<my_table.values IN ALL>> THEN my_table.values
ELSE REPLACE(my_table.values,'all-')
END
ELSE my_table.values
END
) AS values
FROM my_table
GROUP BY 1
我需要检查特定 id
的所有数组 values
是否包含 all-x
,这就是我努力寻找解决方案的地方。
我想合作
经过几个小时的搜索,我开始相信这是不可行的。 任何帮助表示赞赏。感谢阅读。
这应该可以满足您的要求:
WITH my_table(id, my_values) AS (
VALUES
(1, array['all-a','all-b']),
(2, array['all-c','b']),
(3, array['a','b','c']),
(1, array['all-a']),
(2, array[]),
(3, array['all-c'])
),
with_group_counts AS (
SELECT *, count(*) OVER (PARTITION BY id) group_count -- to see if the number of all-X occurrences match the number of rows for a given id
FROM my_table
),
normalized AS (
SELECT
id,
if(
count(*) OVER (PARTITION BY id, value) = group_count AND starts_with(value, 'all-'), -- if its an all-X value and every original row for the given id contains it ...
value,
if(starts_with(value, 'all-'), substr(value, 5), value)) AS extracted
FROM with_group_counts CROSS JOIN UNNEST(with_group_counts.my_values) t(value)
)
SELECT id, array_agg(DISTINCT extracted)
FROM normalized
GROUP BY id
技巧是通过 with_group_counts
子查询中的 count(*) OVER (PARTITION BY id)
表达式计算原始 table 中每个 id 的总行数。然后我们可以使用该值来确定给定值是应该被视为 all-x
还是应该提取 x
。这是由以下表达式处理的:
if(
count(*) OVER (PARTITION BY id, value) = group_count AND starts_with(value, 'all-'),
value,
if(starts_with(value, 'all-'), substr(value, 5), value))
有关 Presto 中 window 函数的更多信息,请查看 documentation. You can find the documentation for UNNEST
here。