По работе столкнулся с необходимостью выполнить хитрую выборку с группировкой из БД. И долго не мог обнаружить решение 🙂
Есть таблица со статусами заказов status, в ней всего 3 столбца: id, order_id, status_id.
Статусы могут повторяться в рамках одного заказа (см. таблицу).
Задача: выбрать все заказы у которых установлены несколько каких-либо статусов (и установлены именно ВСЕ из перечисленных).
| id | order_id | status_id |
| 1 | 1 | created |
| 2 | 1 | stage1 |
| 3 | 1 | stage2 |
| 4 | 1 | stage2 |
| 5 | 1 | stage3 |
| 6 | 1 | stage4 |
| 7 | 2 | created |
До того как я обнаружил, что distinct можно использовать не только в select, запрос некорректно отрабатывал в случаях, когда статусы повторялись. Однако с ним — всё заработало как часы!
Вот пример запроса, который в итоге получился (3 — это по кол-ву статусов в условии WHERE):
SELECT s.order_id
FROM status s
WHERE s.status_id IN ('stage1', 'stage2', 'stage3')
GROUP BY s.order_id
HAVING count(distinct s.status_id) = 3
Т.о. distinct внутри count() делает выборку уникальных статусов, которые мы считаем и проверяем, что их то же количество, которое было в условии WHERE..IN.