Найти пользователей, которые летали только экономом

61. Найти пользователей, которые летали только эконом-классом

Условие задачи:
Дана таблица tickets с информацией о билетах пользователей.

Необходимо вывести уникальные user_id пользователей, у которых все билеты имеют класс ECONOMY.

Если у пользователя есть хотя бы один билет другого класса, например BUSINESS, такой пользователь не должен попасть в результат.

Данные:

ticket_id | user_id | ticket_type | price
----------+---------+-------------+------
110       | 500     | ECONOMY     | 10000
220       | 600     | BUSINESS    | 35000
330       | 600     | ECONOMY     | 15000
440       | 750     | ECONOMY     | 12000
550       | 800     | BUSINESS    | 40000
660       | 750     | ECONOMY     | 5000

Спойлеры к решению

Подсказки
💡 Сгруппируй билеты по user_id.
💡 Посчитай общее количество билетов пользователя.
💡 Отдельно посчитай количество билетов класса ECONOMY.
💡 Пользователь подходит, только если эти два количества равны.

Решение

Основной вариант через GROUP BY и HAVING:

SELECT
    user_id
FROM tickets
GROUP BY user_id
HAVING COUNT(*) =
       COUNT(CASE
                 WHEN ticket_type = 'ECONOMY' THEN 1
             END);

Для каждого пользователя:

COUNT(*)

считает все его билеты, а:

COUNT(CASE
          WHEN ticket_type = 'ECONOMY' THEN 1
      END)

считает только билеты класса ECONOMY.

Если значения равны, значит у пользователя нет билетов другого класса.

Альтернативный вариант через NOT EXISTS:

SELECT DISTINCT
    t.user_id
FROM tickets t
WHERE NOT EXISTS (
    SELECT 1
    FROM tickets other
    WHERE other.user_id = t.user_id
      AND (
          other.ticket_type <> 'ECONOMY'
          OR other.ticket_type IS NULL
      )
);

Здесь из результата исключается пользователь, если у него существует хотя бы один билет, который не является ECONOMY.

Для приведённых данных результат:

user_id
-------
500
750

Пользователь 600 не подходит, поскольку у него есть билет BUSINESS, а пользователь 800 вообще не имеет билетов ECONOMY.