Postgresql 查询检索对话、对话中的最后一条消息、最后一条消息和未读计数

问题描述 投票:0回答:1

我有以下表格:

用户表

id(uuid)
someuuid
someuuid

广告表

id owner_id(用户的 fkey)
someuuid someuuid
someuuid someuuid

留言表

id 广告 发件人(fkey 用户) 接收者(fkey用户) 内容 创建于 read_at(null表示未见)
someuuid someuuid someuuid 一些文字 某天 某天

这意味着每条消息都与广告相关,发送者或接收者是广告的所有者。

现在我想查询每个用户(为了在收件箱中显示)他们所属的每个对话、最后一条消息的内容、该对话中创建最后一条消息的日期以及用户拥有的消息量尚未阅读该对话。

所以继续来说,2 个用户之间的每次对话都与消息的发送者或接收者发布的广告有关

我得到的最远的是能够使用以下查询检索每个对话、该对话中的最后一条消息以及最后一条消息的创建日期

SELECT *
FROM messages
    , (
        SELECT MAX(created_at) AS last_message_sent_at
        FROM messages
        WHERE (
                messages.sender = '80d1c6070a7d' -- ID to compare with (logged in users's ID)
           OR messages.receiver = '80d1c6070a7d' -- ID to compare with (logged in users's ID) 
                )
        GROUP BY ad
        ) AS conversations
WHERE created_at = conversations.last_message_sent_at
ORDER BY messages.created_at DESC LIMIT 100 OFFSET 0
sql database postgresql structure
1个回答
0
投票

为了提供可能发生的情况的示例,请重新考虑问题中给出的详细信息。下面是一些假设的示例数据,可以模拟您的问题以及解决该问题的潜在查询。然而,当我们不知道您的数据实际上是什么样时,很容易犯错误,因此,在考虑许多注意事项的情况下,请考虑下面的示例。 (注意,我使用 varchar(20) 来避免尝试模拟 UUID 时出现问题):

DDL(这样我们就知道我们在处理什么)

CREATE TABLE users (
    id varchar(20) PRIMARY KEY,
    name VARCHAR(100)

);
 
CREATE TABLE ads (
    id varchar(20) PRIMARY KEY,
    owner_id varchar(20) REFERENCES users(id)
);

CREATE TABLE messages (
    id varchar(20) ,
    ad varchar(20) REFERENCES ads(id),
    sender varchar(20) REFERENCES users(id),
    receiver varchar(20) REFERENCES users(id),
    content TEXT,
    created_at TIMESTAMP,
    read_at TIMESTAMP
);

样本数据(假设)

INSERT INTO users (id, name) VALUES
('80d1c6070a7d', 'User1'),
('someuuid2', 'User2'),
('someuuid3', 'User3');

INSERT INTO ads (id, owner_id) VALUES
('ad1', '80d1c6070a7d'),
('ad2', 'someuuid2'),
('ad3', 'someuuid3');


INSERT INTO messages (id, ad, sender, receiver, content, created_at, read_at) VALUES
('msg1', 'ad1', '80d1c6070a7d', 'someuuid3', 'Hello', '2023-11-27 10:00:00', '2023-11-27 10:05:00'),
('msg2', 'ad1', 'someuuid2', '80d1c6070a7d', 'Hi', '2023-11-27 10:02:00', NULL),
('msg3', 'ad2', 'someuuid3', '80d1c6070a7d', 'How are you?', '2023-11-27 11:00:00', NULL),
('msg4', 'ad3', '80d1c6070a7d', 'someuuid2', 'Fine, thank you', '2023-11-27 12:00:00', NULL);

查询

SELECT
      u.id AS user_id
    , u.name AS user_name
    , m.ad AS ad_id
    , a.owner_id AS ad_owner_id
    , m.content AS last_message_content
    , m.created_at AS last_message_created_at
    , COUNT(CASE WHEN m.read_at IS NULL THEN 1 END) AS unread_messages_count
FROM users u
JOIN messages m ON u.id = m.sender
    OR u.id = m.receiver
JOIN ads a ON m.ad = a.id
WHERE u.id = '80d1c6070a7d' -- ID to compare with (logged in user's ID)
GROUP BY
      u.id
    , u.name
    , m.ad
    , a.owner_id
    , m.content
    , m.created_at
ORDER BY
      m.created_at DESC

结果

用户ID 用户名 广告ID ad_owner_id 最后消息内容 最后消息创建时间 未读消息数
80d1c6070a7d 用户1 ad3 someuuid3 好的,谢谢 2023-11-27 12:00:00 1
80d1c6070a7d 用户1 ad2 someuuid2 你好吗? 2023-11-27 11:00:00 1
80d1c6070a7d 用户1 广告1 80d1c6070a7d 2023-11-27 10:02:00 1
80d1c6070a7d 用户1 广告1 80d1c6070a7d 你好 2023-11-27 10:00:00 0

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.