Проблема с INNER JOIN Я не получаю желаемый результат - PullRequest
1 голос
/ 11 апреля 2019

У меня есть таблица с именем last_msg, в которой я храню последнее сообщение из частного чата между двумя пользователями и обновляю столбцы from и to при отправке нового сообщения.Я использую эту таблицу, чтобы показать список сообщений, таких как Facebook.Я также использую эту таблицу для других целей, поэтому я бы скорее решил проблему, описанную ниже.

Из-за ON users.user_id = last_msg.from я получаю данные только от того, кто отправляет сообщения, это было лучшее, что я получил... Это мой текущий sql:

SELECT `last_msg`.`msg`, `last_msg`.`from`, `users`.`username`, `users`.`avatar`
FROM `last_msg` 
    INNER JOIN `users` 
        ON `users`.`user_id` = `last_msg`.`from` 
        WHERE `last_msg`.`to` = :user_id_logged OR `last_msg`.`from` = :user_id_logged_2

На INNER JOIN users я хочу получать данные только от другого пользователя, с которым я общаюсь в чате, а данные от last_msg могутбыть от отправителя и получателя, как это делает facebook.

Итак, я попытался:

SELECT `last_msg`.`msg`, `last_msg`.`from`, `users`.`username`, `users`.`avatar` 
FROM `last_msg` 
    INNER JOIN `users` 
        ON `users`.`user_id` != :user_logged 
        WHERE (`last_msg`.`to` = :user_logged_2 OR `last_msg`.`from` = :user_logged_3)

Но это не сработало, он возвращает список всех пользователей в таблице users,Любые предложения о том, как я могу это исправить?

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

Как получить последние отправленные вам сообщения:

SELECT msg, `from` as other_user_id
FROM last_msg
WHERE `to` = :user_logged;

Если вы также хотите, чтобы сообщения, которые вы отправляли в последний раз:

SELECT msg, `to` as other_user_id
FROM last_msg
WHERE `from` = :user_logged;

Вы говорите, что храните только одно последнее сообщение в чате. Я прочитал это, поскольку для пользователей A и B в таблице будет только одна строка (либо последнее сообщение A, отправленное B, либо последнее сообщение B, отправленное A). Таким образом, вы можете просто объединить два запроса и по-прежнему показывать только одно последнее сообщение в чате.

SELECT m.msg, u.user_id, u.username, u.avatar
FROM
(
  SELECT msg, `from` as other_user_id
  FROM last_msg
  WHERE `to` = :user_logged
  UNION ALL
  SELECT msg, `to` as other_user_id
  FROM last_msg
  WHERE `from` = :user_logged
) m
JOIN users u ON u.user_id = m.other_user_id;

Альтернативой UNION ALL является объединение и CASE WHEN:

SELECT m.msg, u.user_id, u.username, u.avatar
FROM last_msg m
JOIN users u
  ON u.user_id = CASE WHEN :user_logged = m.from THEN m.to ELSE m.from END as other_user_id
WHERE :user_logged IN (m.from, m.to)

Это предложение ON также можно записать как

  ON (u.user_id = m.from AND :user_logged = m.to)
  OR (u.user_id = m.to AND :user_logged = m.from)

или

ON u.user_id IN (m.from, m.to) AND u.user_id <> :user_logged;

кстати. Выберите то, что вам больше нравится.

А вот способ использовать параметр идентификатора пользователя только один раз в запросе:

SELECT m.msg, u.user_id, u.username, u.avatar
FROM (select :user_logged as user_id) myself
JOIN last_msg m ON myself.user_id IN (m.from, m.to)
JOIN users u ON u.user_id IN (m.from, m.to) AND u.user_id <> myself.user_id;
1 голос
/ 11 апреля 2019

Вы можете попытаться присоединиться к таблице пользователей два раза, один для пользователя от, а другой для пользователя, как показано ниже, также обратите внимание, что вам нужно использовать LEFT Join, чтобы получить все от пользователей и для пользователей.

SELECT `last_msg`.`msg`, `last_msg`.`from`, `FromUser`.`username`, `FromUser`.`avatar`,`ToUser`.`username`,`ToUser`.`avatar`
FROM `last_msg` 
    LEFT JOIN `users` as `FromUser` 
        ON `FromUser`.`user_id` = `last_msg`.`from` 
    LEFT JOIN `users` as `ToUser` 
        ON `ToUser`.`user_id` = `last_msg`.`to` 
        WHERE `last_msg`.`to` = :user_id_logged OR `last_msg`.`from` = :user_id_logged_2";

Обновлен код

SELECT `last_msg`.`msg`, `last_msg`.`from`, `users`.`username`, `users`.`avatar` 
FROM `last_msg` 
INNER JOIN `users` 
ON `users`.`user_id` =`last_msg`.`to` 
WHERE `last_msg`.`from`= :user_logged 

UNION 

SELECT `last_msg`.`msg`, `last_msg`.`to`, `users`.`username`, `users`.`avatar` 
FROM `last_msg` 
INNER JOIN `users` 
ON `users`.`user_id` =`last_msg`.`from` 
WHERE `last_msg`.`to`= :user_logged 
...