mysql и INTERSECT
Вобщем не умеет оно его. posgre умеет, sqlite3 - умеет, а этот "стандарт вебмастера" - нет.
Исходные данные:
- a - 500.000 записей
- b - 100.000 записей
- ab ~ 15.000.000 записей (соединяет по идентификатору строку из a с одним или несколькими из b)
-- пиздец, выполняется ~ 12-20 секунд, в зависимости от посторонней нагрузки.
SELECT a_id FROM ab WHERE
b_id = (SELECT b.id FROM b WHERE b.field = <...>);
-- тоже пиздец, хотя при выполнении подзапроса будет то же самое единственное значение
SELECT a_id FROM ab WHERE
b_id IN (SELECT b.id FROM b WHERE b.field = <...>);
-- ...не говоря уже про
SELECT a_id FROM ab WHERE
a_id IN (SELECT a.id FROM a WHERE <...>) AND
b_id IN (SELECT b.id FROM b WHERE <...>);
-- а вот так норм, хотя казалось бы - объединяются 2 нехуёвые таблицы
-- и логически это должно быть эквивалентно первому запросу
-- выполняется такое в моём случае ~ 0.3 секунды
SELECT a_id FROM ab
JOIN b ON (ab.b_id = b.id)
WHERE <...>;
-- и даже вот такое переваривается без особых последствий
SELECT a_id FROM ab
JOIN a ON (ab.a_id = a.id)
JOIN b ON (ab.b_id = b.id)
WHERE <...>; -- куча параметров
-- В интернете народ извращается так:
SELECT all.a_id,COUNT(*) as 'cnt' FROM (
SELECT a.id as 'id' FROM a WHERE <...>
UNION ALL
SELECT b.id as 'id' FROM b WHERE <...>
) as 'all' GROUP BY all.a_id HAVING cnt = 2; -- по количеству запросов
-- работает оно не намного быстрее подзапросов, проверял на той же базе
-- и, если нам внезапно понадобится ещё и EXCEPT - бида-бида