Есть две таблицы.
Таблица 1. Список какого то контента
mysql> desc contents;
+------------------+----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+----------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
+------------------+----------------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
Tаблица 2. Список контента который не нужно отображать.
mysql> desc content_skip;
+-----------------+----------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+----------------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| content_id | int(11) | YES | | 0 | |
+-----------------+----------------------+------+-----+-------------------+----------------+
2 rows in set (0.00 sec)
Суть вопроса в следующем:
Нужно вернуть данные из Таблица 1 такие, которые не входят в таблицу Tаблица 2. Соответственно, есть два решения.
1.
select id from contents where id not in (select content_id from content_skip)
2. Выбрать сразу все id content_skip и потом в перечислении добавить.
select id from contents where id not in (3,4,5)
Первый запрос не нравится DEPENDENT SUBQUERY, а второй тем, что этих id может быть очень большая куча, что в итоге превысит размер пакета запроса.
Вопрос, что можно еще придумать наиболее?
Здравствуйте, MasterMind, Вы писали:
MM>Есть две таблицы.
MM>Нужно вернуть данные из Таблица 1 такие, которые не входят в таблицу Tаблица 2.
Специально для таких случаев существует конструкция NOT EXISTS:
SELECT id
FROM contents c
WHERE NOT EXISTS (
SELECT 1
FROM content_skip cs
WHERE cs.content_id = c.id
)
СУБД должна оптимизировать такие запросы. Если у неё это не получится, то увы, навряд ли получится переизобрести что-либо оптимальнее.
Здравствуйте, MasterMind, Вы писали:
MM>Нужно вернуть данные из Таблица 1 такие, которые не входят в таблицу Tаблица 2. Соответственно, есть два решения.
MM>1.
MM>MM> select id from contents where id not in (select content_id from content_skip)
MM>
MM>2. Выбрать сразу все id content_skip и потом в перечислении добавить.
MM>MM> select id from contents where id not in (3,4,5)
MM>
MM>Первый запрос не нравится DEPENDENT SUBQUERY, а второй тем, что этих id может быть очень большая куча, что в итоге превысит размер пакета запроса.
MM>Вопрос, что можно еще придумать наиболее?
Есть только одно решение, и оно у тебя под номером 1
(ещё есть вариант с коррелированным подзапросом, вводимым NOT EXISTS и с LEFT JOIN и фильтром на отрицательный результат JOIN-а в WHERE,
но это по сути одно и то же -- реализация реляционного вычитания).
Нравится тебе этот вариант или нет -- значения не имеет, потому что другого варианта нет.
И да, этот единственный вариант сложен в смысле вычислительных затрат, не потому, что DEPENDENT SUBQUERY, а потому,
что нужно проверять все сочетания строк из двух таблиц, при наличии индекса (а это очень сильно упростит задачу) --
все строки из внешней таблицы * log( кол-ва строк из внутренней ).
Есть особенности и именно MySQL в этом аспекте, говорят, что некоторые версии оптимизатора в случае с IN материализуют
подзапрос, что плохо. Так что рекомендую проверить план перед выполнением и убедится, что он хороший. (не квадратичный)
Если IN не покатит, замени на NOT EXIST.
Ну и создавай индексы в обоих таблицах по этому ID, если их ещё нет.