How to do this query in Mysql?

无人久伴 提交于 2020-01-05 08:26:32

问题


I have 3 tables, message, subject and message_subject_rel. The idea is to have messages that can relate to a lot of subjects and then do a cross subject search.

Lets say I have a message:

Id: 1, Message: This is a message

2 subjects:

Id:1, Subject: Math
Id:2, Subject: Science

And there's 2 message_subject_rel entries that go:

Id: 1, message_id: 1, subject_id: 1
Id: 2, message_id: 1, subject_id: 2

If i wanted to search the messages that are related with math, I would do a simple join with the 3 tables and the where clause would be subject = "Math"

But what I don't know how to do, is search for the messages that are related with math AND Science. If i do a simple join i get tables with something like:

id  message     user_id     created_at  ip  id  message_id  subject_id  id  subject

And if I do a where subject = "Math" and subject = "Science" i wont get any results because each message will only have 1 subject related in each row, but duplicated rows for messages with more than 1 subject.

So, what do you recommend?


回答1:


This is basically the same question as Filtering from join-table

I'll adapt my answer from that question.

JOIN solution:

SELECT m.*
FROM messages m
 JOIN message_subject_rel ms1 ON (m.id = ms1.message_id)
 JOIN subjects s1 ON (ms1.subject_id = s1.id AND s1.subject = 'Math')
 JOIN message_subject_rel ms2 ON (m.id = ms1.message_id)
 JOIN subjects s2 ON (ms2.subject_id = s2.id AND s2.subject = 'Science');

GROUP BY solution:

Note that you need to list all m.* columns in the GROUP BY clause, unless you use MySQL.

SELECT m.*
FROM messages m 
 JOIN message_subject_rel ms ON (m.id = ms.message_id)
 JOIN subjects s ON (ms.subject_id = s.id)
WHERE s.subject IN ('Math', 'Science'))
GROUP BY m.id, ...
HAVING COUNT(*) = 2;

Subquery solution:

SELECT m.*
FROM messages m
WHERE m.id = ANY (SELECT message_id 
                  FROM message_subject_rel ms JOIN subjects s 
                    ON (ms.subject_id = s.id) 
                  WHERE s.subject = 'Math')
  AND m.id = ANY (SELECT message_id 
                  FROM message_subject_rel ms JOIN subjects s 
                    ON (ms.subject_id = s.id) 
                  WHERE s.subject = 'Science');

Modified GROUP BY solution:

Simplifies GROUP BY clause by isolating search in a subquery.

SELECT m.*
FROM messages m
WHERE m.id IN (
  SELECT ms.message_id FROM message_subject_rel ms JOIN subjects s
    ON (ms.subject_id = s.id)
  WHERE s.subject IN ('Math', 'Science'))
  GROUP BY ms.message_id HAVING COUNT(*) = 2
);

PS: There's no reason your message_subject_rel table needs an ID column.




回答2:


Do an inner select in your where clause.

SELECT FROM [tables and joins] WHERE subject = "Math" AND message_id IN (SELECT message_id FROM [tables and joins] WHERE subject = "Science")



来源:https://stackoverflow.com/questions/652484/how-to-do-this-query-in-mysql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!