У меня есть 2 таблицы ниже:
Сообщения
В этой таблице для конкретного сообщения, если оно имеет тип «Q», это вопрос. Еще это разговор двух пользователей.
Таблица разговоров
Это отслеживает разговоры и имеет идентификатор пользователя и пользователя ответа
Теперь из приведенной выше таблицы я хотел бы получить все сообщения, которые не относятся к типу Q
и userid
этого сообщения не должно быть answeruserid
для соответствующего вопроса в таблице беседы. id
в таблице сообщений - это questionid
в таблице беседы.
Вот что я пробовал:
SELECT
*
FROM
chekmarc.messages AS a
WHERE
userid NOT IN
(
SELECT
answeruserid
FROM
chekmarc.conversations AS b
WHERE
a.id = b.questionid
)
AND
a.type != 'Q';
Но NOT IN
соответствует многоуровневым ссылкам, поэтому здесь работать не будет.
Вот что я попробовал дальше:
SELECT
m.*,
c.*
FROM
chekmarc.messages m
INNER JOIN
(
SELECT
*
FROM
chekmarc.conversations c
WHERE
answeruserid IS NOT NULL
AND
questionid IS NOT NULL
) c ON
c.questionid = m.id
AND
m.userid = c.answeruserid
WHERE
m.type != 'Q'
AND
m.userid IS NOT NULL
AND
m.id IS NOT NULL;
Но я получаю несовпадающие строки и желаемый результат. Как я могу этого добиться?
Спасибо.
ОБНОВЛЕНИЕ:
- Один
id
из таблицы сообщений может быть несколькоquestionid
из таблицы разговоров. Когда пользователь начинает беседу, новая строка вставляется под беседы и ссылается наquestionid
(идентификатор сообщения с типом = 'Q', который был опубликован) - Например, когда я (скажем, пользователь A) задаю вопрос «помогите мне», несколько пользователей теперь могут начать разговор по этому вопросу. Теперь «помогите мне» хранится в сообщениях с типом «Q», чтобы показать, что это был вопрос. Когда пользователь говорит, что пользователь B начинает беседу со мной по вопросу "помогите мне", новая строка вставляется под беседы, показывая пользователя A
userid
(какquestionuserid
) и пользователя B (как {{X2}) }). С этого момента любые сообщения будут храниться в таблицеmessages
(либо пользователя A, либо B). Итак, если бы мы получили все обращения, относящиеся к пользователю B для сообщения, мы можем проверить в беседе, не совпадает лиuserid
в таблице сообщений сquestionuserid
в таблице беседы. - Таблицы не имеют ограничений отношения
2 ответа
Я считаю, что это сработает:
SELECT
*
FROM
messages AS m1
INNER JOIN conversations AS c1 ON m1.conversationid = c1.id
WHERE
m1.type <> 'Q'
AND
m1.userid <> c1.answeruserid
Помните, что JOIN
(совпадающие строки) - это не то же самое, что предикат WHERE x IN ( SELECT y FROM z )
, даже если они оба могут вызывать одинаковые результаты (но только в тривиальных запросах).
Понимание того, как работают JOIN
(и когда их использовать) - одна из самых сложных частей для понимания SQL. Я бы хотел, чтобы в учебниках и руководствах по SQL вводились подзапросы после JOIN
s, иначе люди получат неправильную мысленную модель SQL.
Я хотел бы получить все сообщения, которые не относятся к типу Q, и идентификатор пользователя этого сообщения не должен быть answeruserid для соответствующего вопроса в таблице разговоров. Идентификатор в таблице сообщений - это идентификатор вопроса в таблице беседы.
Думаю, вы хотите not exists
:
SELECT m.*
FROM messages
WHERE m.type <> 'Q' AND
NOT EXISTS (SELECT 1
FROM conversations c
WHERE m.id = c.questionid AND
m.userid = c.answeruserid
);
Похожие вопросы
Новые вопросы
mysql
MySQL - это бесплатная система управления реляционными базами данных с открытым исходным кодом (RDBMS), использующая язык структурированных запросов (SQL). НЕ ИСПОЛЬЗУЙТЕ этот тег для других БД, таких как SQL Server, SQLite и т. Д. Это разные БД, которые все используют свои собственные диалекты SQL для управления данными.