Рассмотрим две таблицы:
Foo:
id INT,
name VARCHAR
Bar:
id INT,
foo_id INT REFERENCES Foo(id),
event_type VARCHAR DEFAULT NULL,
event_duration INT DEFAULT NULL
Каждый элемент Foo может иметь несколько событий Bar. Как запросить элементы Foo, у которых нет событий Bar, отвечающих любому из следующих условий:
event_type
, не являющееся одним из следующих значений: 'miss', 'scratch', 'scrape'event_duration
, который не равен нулю
Например, рассмотрим:
Foo id=1:
event_type: hit | event_duration: NULL
event_type: poke | event_duration: NULL
event_type: capture | event_duration: NULL
Foo id=2:
event_type: hit | event_duration: 2
event_type: poke | event_duration: NULL
event_type: capture | event_duration: NULL
Foo id=3:
event_type: miss | event_duration: NULL
event_type: poke | event_duration: NULL
event_type: capture | event_duration: NULL
Foo id=4:
event_type: strike | event_duration: NULL
event_type: hit | event_duration: NULL
event_type: land | event_duration: NULL
Должны быть возвращены только элементы Foo с id=1
и id=4
. Элемент с id=2
не должен возвращаться, так как один из его event_duration
не равен NULL. Элемент с id=3
не должен быть возвращен, так как один из его event_type
является miss
(который находится в списке запрещенных типов_событий).
Я пробовал различные идеи из этот потрясающий ответ, который отвечает на обобщение ситуации, из которой я надеялся узнать достаточно чтобы построить этот запрос. Увы, мне не удалось достаточно обобщить ответ, чтобы решить эту проблему. Это один из примеров неработающего запроса, других неудачных попыток было довольно много:
SELECT
f.name
FROM
Foo f JOIN Bar b ON f.id = b.foo_id
GROUP BY
b.event_type, b.event_duration
HAVING
b.event_type not in ('miss', 'scratch', 'scrape')
AND
b.event_duration not null
Вот еще один нерабочий запрос:
SELECT
f.name
FROM
(
SELECT
f.name, b.event_duration
FROM
Foo f JOIN Bar b ON f.id = b.foo_id
GROUP BY
b.event_type
HAVING
b.event_type not in ('miss', 'scratch', 'scrape')
)
GROUP BY
b.event_duration
HAVING
b.event_duration not null
Было много других неработающих запросов с несколькими идеями о JOIN и подзапросах. Обратите внимание, что в таблице Foo
почти 5 миллионов строк, а в таблице Bar
почти 2 миллиона строк. Таблицы индексируются по соответствующим полям, но O(n^2)
на таких больших таблицах это просто невозможно.