开发者

mysql complex joins

开发者 https://www.devze.com 2023-01-24 08:59 出处:网络
This is relating to mysql query with AND, OR and NOT and also mysql has all values I 开发者_StackOverflow中文版have solved the AND part of the problem, but Now I also now need to solve the OR and the

This is relating to mysql query with AND, OR and NOT and also mysql has all values I 开发者_StackOverflow中文版have solved the AND part of the problem, but Now I also now need to solve the OR and the NOT.

Just to confirm the below statement gives me all articles that have each topic 1, 2 and 3

SELECT x.*
FROM Article x INNER JOIN
(SELECT t.article_id, COUNT(t.article_id)
  FROM articleTopics t
  WHERE t.topic_id IN ('1','2','3')
  GROUP BY t.article_id
  HAVING COUNT(t.article_id)>=3
  ORDER BY COUNT(t.article_id) DESC
  LIMIT 0,100) AS ilv
ON x.id=ilv.article_id

What I am trying to do is add something to the query that would exclude all articles that are also associated with topics 4 and 5. : NOT

I will also want to add the articles that have topics 6, or 7 as long as they match the previous constraints.

E.g.

SELECT all Articles where the articles has
    all the following topics (1,2,3) #AND
AND
    none of the following topics (4,5) #NOT
AND
    may have any of the following topics(6,7) #OR

I hope that makes sense!


I would use the EXISTS function like:

SELECT ...
FROM Article a
WHERE EXISTS (SELECT topic_id FROM articleTopics t WHERE t.article_id = a.article_id AND topic_id = 1)
  AND EXISTS (SELECT topic_id FROM articleTopics t WHERE t.article_id = a.article_id AND topic_id = 2)
  AND EXISTS (SELECT topic_id FROM articleTopics t WHERE t.article_id = a.article_id AND topic_id = 3)
  AND NOT EXISTS (SELECT topic_id FROM articleTopics t WHERE t.article_id = a.article_id AND topic_id = 4)
  AND NOT EXISTS (SELECT topic_id FROM articleTopics t WHERE t.article_id = a.article_id AND topic_id = 5)
  AND (EXISTS (SELECT topic_id FROM articleTopics t WHERE t.article_id = a.article_id AND topic_id = 6)
    OR EXISTS (SELECT topic_id FROM articleTopics t WHERE t.article_id = a.article_id AND topic_id = 7))


Seems like it would be much simpler to use a regular JOIN than to use a subselect. Should be faster too.

SELECT * FROM articles JOIN articleTopics USING(article_id) 
 WHERE topic_id IN(1,2,3) AND topic_id NOT IN (4,5) GROUP BY article_id;

I don't see why you need to specify 6 and 7. Unless you're saying if it has 6 or 7 the other rules don't matter. In which case you could do:

SELECT * FROM articles JOIN articleTopics USING(article_id) 
  WHERE (topic_id IN(1,2,3) AND topic_id NOT IN (4,5)) OR topic_id IN(6,7) GROUP BY article_id;


This is what I ended up with:

SELECT x.*
FROM Article x INNER JOIN
(SELECT t.article_id, COUNT(t.article_id)
  FROM articleTopics t
  WHERE t.topic_id IN ('1','2','3')
  AND NOT EXISTS (
       SELECT 1
       FROM articleTopics
       WHERE article_id = t.article_id
       AND entity_id IN ('4','5'))
  GROUP BY t.article_id
  HAVING COUNT(t.article_id)>=3
  ORDER BY COUNT(t.article_id) DESC
  LIMIT 0,100) AS ilv
ON x.id=ilv.article_id
LEFT JOIN articleTopics at ON at.article_id = x.id
WHERE ae_topic_id IN ('6','7')

This says all articles must contain all topics 1,2,3 and atleast 1 from 6 or 7 but never include 4 or 5

Thanks for your help on this.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号