Выбрать записи не содержащие теги ( sql )

298
26 ноября 2016, 20:20

Есть 3 таблицы: посты ( post ) теги ( tag ) связь тегов и постов ( post_tag )

Стандартная таблица связей

post_id | tag_id
      1 | 4
      1 | 6
      2 | 5
      3 | 6
      4 | 5
      4 | 7
      6 | 8
      7 | 8

Необходимо получить все посты у которых нет тегов 4 и 5 ( и дополнительным условием является исключение уже просмотренных постов, допустим посмотрел посты с ид 6 и 7 )

Делаю запросом:

SELECT  post_id 
FROM post_tag
WHERE post_id NOT IN ( 
SELECT DISTINCT post_id FROM post_tag WHERE tag_id IN (4,5) 
) AND post_id NOT IN (6,7)
mysql> explain SELECT DISTINCT `idVideo` FROM `video_tag` WHERE `idVideo` NOT IN (SELECT DISTINCT idVideo FROM video_tag WHERE idTag IN (263,469,478,482,537,904,967)) AND (`idVideo`<>239529) AND (`quality`=100);
+----+-------------+-----------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+---------+------+---------+--------------------------+
| id | select_type | table     | type  | possible_keys                                                                                                                                                                        | key                        | key_len | ref  | rows    | Extra                    |
+----+-------------+-----------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+---------+------+---------+--------------------------+
|  1 | PRIMARY     | video_tag | index | PRIMARY,video_tag-idVideo-video-id,video_tag-idVideo-idTag,video_tag-idVideo-idTag-quality,video_tag-idTag-idVideo-quality,video_tag-idTag-idVideo,video_tag-idTag,video_tag-idVideo | video_tag-idVideo-video-id | 4       | NULL | 4629680 | Using where              |
|  2 | SUBQUERY    | video_tag | range | PRIMARY,video_tag-idVideo-video-id,video_tag-idVideo-idTag,video_tag-idVideo-idTag-quality,video_tag-idTag-idVideo-quality,video_tag-idTag-idVideo,video_tag-idTag,video_tag-idVideo | PRIMARY                    | 4       | NULL |  372807 | Using where; Using index |
+----+-------------+-----------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------+---------+------+---------+--------------------------+
2 rows in set (0.01 sec)

Количество индексов для теста.

Запрос отрабатывает ужасно медленно. Как бы ускорить это дело?

Answer 1

Попробуйте такой вариант:

SELECT post_id 
  FROM post_tag
 WHERE post_id NOT IN (6,7)
 GROUP BY post_id
 HAVING sum( tag_id IN (4,5) ) = 0

Или такой:

SELECT post.id 
  FROM post
  LEFT JOIN post_tag ON tag_id IN (4,5) and post.id=post_tag.post_id
 WHERE post_tag.post_id IS NULL and post.id NOT IN (6,7)
READ ALSO
Формировать ли запрос в MySQL поблочно или делать простыню?

Формировать ли запрос в MySQL поблочно или делать простыню?

Воюю с простыней, запросы в коде PHP 120-140 строк по 80-100 символов, те

255
Реализация insert ignore в Sqlalchemy orm

Реализация insert ignore в Sqlalchemy orm

Пытаюсь разобраться в sqlalchemy, подскажите, пожалуйста, как реализовать insert ignore при использовании sqlalchemy ormИмеем три таблицы вида:

329
Подключение к базе данных mysql

Подключение к базе данных mysql

Доброго времени сутокСкажите, а можно ли этот метод, который подключается к БД с изменениями внести в ActionListener для кнопки

247
Непонятный запрос Yii2

Непонятный запрос Yii2

У меня постоянно показывает такой запрос

250