Presto 是否支持 NOT IN 结构?

Does Presto support NOT IN constructs?

我有以下形式的查询:

SELECT DISTINCT person_id
FROM my_table
WHERE person_id NOT IN (SELECT person_id FROM my_table WHERE status = 'hungry')

my_table 中,每个人都有多行,我想排除那些曾拥有身份 "hungry" 的人。这是我认为是标准的构造,并在其他 SQL 方言中使用过,但这使我在 Athena 中返回了一个空结果集。

另一方面,普通的旧 IN 结构按预期工作。

谁能解释一下我如何在 Presto 中编写此查询?我在 SO 上发现 似乎暗示它可以正常工作,所以我有点不知所措。

我会做聚合:

SELECT person_id
FROM my_table
GROUP BY person_id
HAVING SUM(CASE WHEN status = 'hungry' THEN 1 ELSE 0 END) = 0;

如果你想要整行然后使用 NOT EXISTS ,NOT IN 将 return 如果子查询有 null 则没有行 :

SELECT DISTINCT t.person_id
FROM my_table t
WHERE NOT EXISTS (SELECT 1  
                  FROM my_table t1
                  WHERE t1.status = 'hungry' AND
                        t1.person_id = t.person_id
                 );    

不要使用NOT IN。如果 any 返回值是 NULL 那么它 returns 没有行。注意:这就是 SQL 的工作方式,而不是任何特定数据库的特性。

而是使用 NOT EXISTS:

SELECT DISTINCT t.person_id
FROM my_table t
WHERE NOT EXISTS (SELECT  
                  FROM my_table t2
                  WHERE t2.status = 'hungry' AND
                        t2.person_id = t.person_id
                 );

实际上,我可能建议对此进行聚合——您基本上已经在使用 SELECT DISTINCT:

进行聚合
select person_id
from my_table t
group by person_id
having sum(case when status = 'hungry' then 1 else 0 end) = 0;

使用条件聚合:

SELECT person_id
FROM my_table m
GROUP BY person_id
HAVING COUNT(CASE WHEN status='hungry' THEN 1 END)=0

我不得不指出,您可以通过从子查询中显式排除 NULL 并坚持使用 NOT IN 构造来解决此问题:

SELECT DISTINCT person_id
FROM my_table
WHERE person_id NOT IN (SELECT person_id FROM my_table WHERE status = 'hungry' AND person_id IS NOT NULL)