Как сделать этот запрос в Mysql? - PullRequest
1 голос
/ 17 марта 2009

У меня есть 3 таблицы, сообщение, тема и message_subject_rel. Идея состоит в том, чтобы иметь сообщения, которые могут относиться ко многим темам, а затем выполнять межсубъектный поиск.

Допустим, у меня есть сообщение:

Id: 1, Message: This is a message

2 предмета:

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

И есть 2 message_subject_rel записей, которые идут:

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

Если бы я хотел искать сообщения, связанные с математикой, я бы сделал простое объединение с 3 таблицами, и предложение where было бы subject = "Math"

Но я не знаю, как это сделать, - искать сообщения, связанные с математикой и наукой. Если я делаю простое соединение, я получаю таблицы с чем-то вроде:

id  message     user_id     created_at  ip  id  message_id  subject_id  id  subject

И если я сделаю where subject = "Math" and subject = "Science", я не получу никаких результатов, поскольку каждое сообщение будет иметь только 1 тему, связанную в каждой строке, но дублированные строки для сообщений с более чем 1 темой.

Итак, что вы рекомендуете?

Ответы [ 2 ]

3 голосов
/ 17 марта 2009

Это в основном тот же вопрос, что и Фильтрация из таблицы соединений

Я адаптирую свой ответ на этот вопрос.

РЕШЕНИЕ РЕШЕНИЯ:

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:

Обратите внимание, что вам нужно перечислить все столбцы m. * В предложении GROUP BY, если вы не используете 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;

Решение подзапроса:

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');

Модифицированное решение GROUP BY:

Упрощает предложение GROUP BY, изолируя поиск в подзапросе.

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: Нет никакой причины, по которой вашей таблице message_subject_rel нужен столбец ID.

0 голосов
/ 17 марта 2009

Сделайте внутренний выбор в предложении where.

SELECT FROM [таблицы и объединения] WHERE subject = "Math" И message_id IN (SELECT message_id FROM [таблицы и объединения] WHERE subject = "Science")

...