Это относится к моему последнему запросу mysql-запроса с AND, OR и NOT
Вместо того, чтобы редактировать вопрос, я задаю новый вопрос, потому что вопрос является лишь частью предыдущего вопроса с изменением.
Я ищу сделать mysql-запрос, который возвращает мне все статьи, в которых есть все необходимые темы.
Article id .... Topic id .... ArticleTopics article_id topic_id type
что бы эффективно делало:
SELECT * FROM Article LEFT JOIN ArticleTopics ON Article.id = ArticleTopics.article_id WHERE ArticleTopics.topic_id HAS ALL (these topics)
Это возможно? Каков наилучший подход для этого?
Некоторые из других ответов предполагают использование псевдонимов в дочерней таблице для каждой статьи фильтра – это может быть не очень эффективно или хорошо масштабироваться.
Рассматривать:
SELECT x.* FROM Article x INNER JOIN (SELECT t.article_id, COUNT(t.article_id) FROM articleTopics t WHERE t.topic_id IN ([your_list_of_topics]) GROUP BY t.article_id HAVING COUNT(t.article_id)>=[number of elements in [your_list_of_topics]] ORDER BY COUNT(t.article_id) DESC LIMIT 0,100) AS ilv ON x.id=ilv.article_id
Другим преимуществом этого подхода является то, что структура запроса не нуждается в изменении с количеством тем, которые вы ищете, – вы даже можете поместить их во временную таблицу и выполнить соединение вместо использования «IN (.. .) 'литерал.
Вам нужно попробовать, чтобы увидеть, какой запрос ведет себя лучше.
Это делается с использованием нескольких соединений с одной и той же таблицей.
Чтобы выбрать все статьи, в которых есть темы с идентификаторами 1, 2 и 3, вам нужно сделать:
SELECT * FROM Article a INNER JOIN ArticleTopics at1 ON a.id = at1.article_id AND at1.topic_id = 1 INNER JOIN ArticleTopics at2 ON a.id = at2.article_id AND at2.topic_id = 2 INNER JOIN ArticleTopics at3 ON a.id = at3.article_id AND at3.topic_id = 3
// EDIT Исправлено. Добавлены псевдонимы таблицы; Должно быть, я слишком долго работал с хорошими решениями ORM …
SELECT * FROM Article WHERE (SELECT COUNT(*) FROM ArticleTopics WHERE Article.id = ArticleTopics.article_id AND ArticleTopics.topic_id=1) > 0 AND (SELECT COUNT(*) FROM ArticleTopics WHERE Article.id = ArticleTopics.article_id AND ArticleTopics.topic_id=2) > 0 AND (SELECT COUNT(*) FROM ArticleTopics WHERE Article.id = ArticleTopics.article_id AND ArticleTopics.topic_id=3) > 0 AND ...