Presto 在聚合期间过滤数组

Presto filter an array during aggregation

我想根据与 id 关联的所有值来过滤聚合数组。值是字符串,可以是 all-x:yx:y 和空三种类型(这里 xy 是值的任意子字符串)。

我有几个条件:

  1. 如果 idx:y 那么结果应该包含 x:y.
  2. 如果 id 总是 all-x:y 那么生成的聚合应该有 all-x:y
  3. 如果 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