У меня есть 2 таблицы ниже:

Сообщения

enter image description here

В этой таблице для конкретного сообщения, если оно имеет тип «Q», это вопрос. Еще это разговор двух пользователей.

Таблица разговоров

Это отслеживает разговоры и имеет идентификатор пользователя и пользователя ответа

enter image description here

Теперь из приведенной выше таблицы я хотел бы получить все сообщения, которые не относятся к типу 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 в таблице беседы.
  • Таблицы не имеют ограничений отношения
0
rohan sethi 11 Окт 2020 в 14:11

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.

1
Dai 11 Окт 2020 в 11:27

Я хотел бы получить все сообщения, которые не относятся к типу 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
                 );
0
Gordon Linoff 11 Окт 2020 в 11:58