#mysql #sql
#mysql #sql
Вопрос:
У меня есть следующая таблица:
---- ------- ---------
| id | media | status |
---- ------- ---------
| 1 | FOO | ACTIVE |
| 1 | FOO | PENDING |
| >1 | BAR | ACTIVE |
| 2 | FOO | ACTIVE |
| 2 | FOO | PENDING |
| >3 | BAR | ACTIVE |
---- ------- ---------
Что мне нужно получить, так это список id
, в котором есть ACTIVE
записи с определенным media
значением, но нет PENDING
записи с таким же media
значением. В моем примере id=1
покрыли FOO
, но не раскрыли BAR
.
Таким образом, результирующая таблица должна быть:
----
| id |
----
| 1 |
| 3 |
----
Единственное решение, которое я вижу, — создать две таблицы с ACTIVE
и PENDING
записями отдельно, затем найти записи, которые есть только в ACTIVE
, а не в PENDING
нет. Но я понятия не имею, как построить запрос.
Пожалуйста, сообщите.
Комментарии:
1. Если идентификатор имеет два типа носителей, один с ожиданием, другой без, должен ли он все еще быть включен?
2. О, мои извинения. Если
id
имеет только ожиданиеmedia
, то оно не включено.3. Я спрашиваю о том, где у одного идентификатора есть два разных типа носителей, и у одного есть ожидание, а другой только активен. Смотрите мой ответ о практической разнице.
Ответ №1:
Я бы сделал это с помощью group by
и having
, потому что это очень гибкий способ формулирования запросов такого типа:
select id
from table t
group by id, media
having sum(status = 'ACTIVE') > 0 and
sum(status = 'PENDING') = 0;
Комментарии:
1. что, если OP имеет более 2 статусов?? например, активный, ожидающий, с истекшим сроком действия, удержание?
2. @timus2001 . . . Это будет работать так, как написано. Кроме того, легко добавить дополнительные правила, такие как не более одного просроченного и трех удерживаемых.
Ответ №2:
Использование соединения по ЛЕВОМУ краю:-
SELECT a.id
FROM some_table a
LEFT OUTER JOIN some_table b
ON a.id = b.id
AND a.media = b.media
AND a.status = 'ACTIVE'
AND b.status = 'PENDING'
WHERE b.id IS NULL
Этот self присоединяется к таблице, один для активных и один для ожидающих. Проверяет, что b.id ИМЕЕТ значение NULL для проверки отсутствия совпадения.
Ответ №3:
SELECT DISTINCT id
FROM t
GROUP BY id, media
HAVING MAX(status) = 'ACTIVE';
Это предполагает, что идентификатор, который имеет ожидающий носитель, все равно должен быть включен, если он также имеет другой тип носителя без ожидающего. Если это неверно или неприменимо, вы можете удалить DISTINCT
из SELECT и media
из GROUP BY.
Ответ №4:
Вы можете использовать предложение NOT EXISTS (также подойдет предложение NOT IN).
select distinct id
from table t
where status = 'ACTIVE'
and not exists (select null
from table
where t.id = id and t.media = media
and status = 'PENDING')
смотрите SQLFiddle
Ответ №5:
ОБЪЕДИНЕНИЕ ГРУПП
select id from tbl group by media,id
having group_concat(status)='active'
Комментарии:
1. Это будет включать строки, содержащие только
PENDING
.2. Активен в ожидании чего угодно… я разберусь с этим завтра .. здесь поздняя ночь 🙂
3. Не уверен, какое отношение имеют уникальные наборы к чему-либо, но ваш первый запрос определенно будет включать
id
запросы, которые имеют толькоPENDING
статусы.4. Да .. op не упомянул, что ему это нужно только для active … это работает для любого уникального набора… если op нужен конкретный, он может, наконец, добавить предложение where … я предпочитаю общий sql, а не жестко закодированный .. подумайте, прежде чем отклонять
5. отредактировано … OP только что прокомментировал, что он нужен исключительно только для active