Presto поддерживает конструкции NOT IN? - PullRequest
0 голосов
/ 13 марта 2020

У меня есть запрос в форме:

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

В my_table есть несколько строк для каждого человека, и я хочу исключить тех людей, которые когда-либо имели статус «голодный». Это конструкция, которую я считаю стандартной и использовала в других диалектах SQL, но это возвращает меня к пустому результирующему набору в Афине.

С другой стороны, простая старая конструкция IN работает как ожидается.

Может кто-нибудь объяснить, как я могу написать этот запрос в Presto? Я нашел еще одну статью о SO, которая, кажется, подразумевает, что она работает правильно, поэтому я немного растерялся.

Ответы [ 4 ]

1 голос
/ 13 марта 2020

Не использовать NOT IN. Если какие-либо возвращенные значения равны NULL, то он не возвращает строк. Примечание: это то, как работает 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;
1 голос
/ 13 марта 2020

Использование условного агрегирования:

SELECT person_id
FROM my_table m
GROUP BY person_id
HAVING COUNT(CASE WHEN status='hungry' THEN 1 END)=0
1 голос
/ 13 марта 2020

Я бы сделал агрегацию:

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 не вернет строку, если подзапрос имеет значение 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
                 );    
0 голосов
/ 13 марта 2020

Я чувствую себя обязанным указать, что вы можете решить эту проблему, просто исключив значения 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)
...