Задать вопрос
@Totobi

Как правильно вывести последнее сообщение в блок слева который будет на картинке?

Здравствуйте, пробую делать простой чат.

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

+----+-------------+------------+--------+--------------+------------+
| id | message     | date       | status | from_user_id | to_user_id |
+----+-------------+------------+--------+--------------+------------+
|  1 | sfgsfdgsfdg | 1693310921 |      0 |           15 |         20 |
|  2 | aboba       | 1693317654 |      0 |           20 |         15 |
|  3 | 123         | 1693318102 |      0 |           19 |         15 |
|  4 | 321         | 1693318124 |      0 |           15 |         19 |
+----+-------------+------------+--------+--------------+------------+


SELECT
        messages.*,
        users.login,
        image.img
    FROM 
         messages
    LEFT JOIN
          users ON messages.to_user_id = users.id
    LEFT JOIN
           image ON messages.to_user_id = image.obj_id AND image.obj_type = 'user'
     WHERE
          messages.date = (SELECT MAX(date) FROM messages WHERE from_user_id = :id AND to_user_id = :id)


Вот запрос который пробовал выполнять, но это не то что мне надо:
скрин
64ee03a0b7fef190430038.png
  • Вопрос задан
  • 213 просмотров
Подписаться 1 Простой 2 комментария
Пригласить эксперта
Ответы на вопрос 4
@pantsarny
Select message from messages where from_user_id in ($user_id, $peer_id) and to_user_id in ($user_id, $peer_id) order by date desc limit 1
Ответ написан
vndrussia
@vndrussia
Вроде разработчик,а вроде и нет
Сообщения:
+----+---------+------------+--------+--------------+------------+
| id | message | date       | status | from_user_id | to_user_id |
+----+---------+------------+--------+--------------+------------+
| 1  | ...     | 1693310921 | 0      | 15           | 20         |
| 2  | ...     | 1693317654 | 0      | 20           | 15         |
| 3  | ...     | 1693318102 | 0      | 19           | 15         |
| 4  | ...     | 1693318124 | 0      | 15           | 19         |
+----+---------+------------+--------+--------------+------------+

Юзеры:
+----+---------+
| id | login   |
+----+---------+
| 15 | user1   |
| 19 | user2   |
| 20 | user3   |
+----+---------+

Тогда запрос будет примерно такой:
SELECT
    m1.*,
    u1.login AS from_user_login,
    u2.login AS to_user_login
FROM
    messages m1
JOIN
    (
        SELECT
            LEAST(from_user_id, to_user_id) AS user1_id,
            GREATEST(from_user_id, to_user_id) AS user2_id,
            MAX(date) AS max_date
        FROM
            messages
        GROUP BY
            LEAST(from_user_id, to_user_id),
            GREATEST(from_user_id, to_user_id)
    ) m2 ON LEAST(m1.from_user_id, m1.to_user_id) = m2.user1_id
        AND GREATEST(m1.from_user_id, m1.to_user_id) = m2.user2_id
        AND m1.date = m2.max_date
JOIN
    users u1 ON m1.from_user_id = u1.id
JOIN
    users u2 ON m1.to_user_id = u2.id;


Могу ошибаться,редко составляю такие громоздкие запросы.
Но суть вроде передал верно.

P.S я бы может более костыльно сделал но:
Сделать таблицу last_msg
и писать в нее id(unic auto),to_user,from_user,message
И просто при отправке сообщения опред юзеру обновлять данную таблицу и хранить в ней последнее сообщение всегда.А выводить по to_user где to_user = id просматривающего.
Ответ написан
Комментировать
ThunderCat
@ThunderCat Куратор тега PHP
{PHP, MySql, HTML, JS, CSS} developer
SELECT m.*, u.login, i.img
    FROM messages m
    LEFT JOIN users u
    ON m.to_user_id = u.id
    LEFT JOIN image i 
    ON m.to_user_id = i.obj_id 
    WHERE m.date > :lastdate # надо выбирать все что позже уже полученных сообщений
    AND image.obj_type = 'user' 
    AND m.from_user_id = :fid  # айди "от юзера"
    AND m.to_user_id = :tid #айди "к юзеру"
    ORDER BY m.date  # по возрастанию все старше последнего полученного
Ответ написан
Комментировать
@Totobi Автор вопроса
ThunderCat , Даниил, pantsarny
вот запрос к которому Я пришел и он достает то что мне надо. Но Я столкнулся с проблемой, в PDO нельзя везде установить одно название для бинда значения и Я сделал вот так (код после текста), но мне кажется так неправильно делать. Можете что-то посоветовать?
public function dialogueList($id)
    {
        try
        {
           
            $query = "
            SELECT
                m.message,
                m.date,
                u.login AS interlocutor_name,
                i.img AS interlocutor_img
            FROM messages m
            JOIN (
                SELECT MAX(date) AS max_date, dialog_id
                FROM messages
                WHERE from_user_id = :id1 OR to_user_id = :id2
                GROUP BY dialog_id
            ) t ON m.dialog_id = t.dialog_id AND m.date = t.max_date
            JOIN users u ON
                (CASE
                    WHEN m.from_user_id = :id3 THEN m.to_user_id = u.id
                    WHEN m.to_user_id = :id4 THEN m.from_user_id = u.id
                END)
            LEFT JOIN 
                image i ON u.id = i.obj_id AND i.obj_type = 'user' 
            WHERE m.from_user_id = :id5 OR m.to_user_id = :id6
            ";
            $stmt = $this->db->prepare($query);
            $stmt->bindValue(":id1", $id, PDO::PARAM_INT);
            $stmt->bindValue(":id2", $id, PDO::PARAM_INT);
            $stmt->bindValue(":id3", $id, PDO::PARAM_INT);
            $stmt->bindValue(":id4", $id, PDO::PARAM_INT);
            $stmt->bindValue(":id5", $id, PDO::PARAM_INT);
            $stmt->bindValue(":id6", $id, PDO::PARAM_INT);
            $stmt->execute();
            $data = $stmt->fetchAll();

            return $data;
        }
        catch(PDOException $e)
        {
            echo $e;
        }
    }
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы