如何在SQL查询中获取每个用户的未读消息数和最后一条消息?

时间:2018-10-25 23:38:00

标签: sql postgresql

我有一个这样的消息表:

message_id | body         | from_user_id | to_user_id | is_read | sent_date 
---------------------------------------------------------------------------
1          | hello        | 23           | 31         | false   | 2 min ago
---------------------------------------------------------------------------
2          | thank you    | 28           | 31         | true    | 4 min ago
---------------------------------------------------------------------------
3          | how are you? | 31           | 28         | false   | 1 min ago
---------------------------------------------------------------------------
4          | a-ha         | 29           | 31         | false   | 6 min ago

我想获取当前用户的未读消息数和最后一条消息(例如user_id 31)

所需结果:

from_user_id | to_user_id | body         | sent_date | unread_message_count 
-------------------------------------------------------------------
23           | 31         | hello        | 2 min ago | 1
-------------------------------------------------------------------
31           | 28         | how are you? | 1 min ago | 0
-------------------------------------------------------------------
29           | 31         | a-ha         | 6 min ago | 1

我使用了以下代码:

WITH ranked_messages AS (
    SELECT 
         messages.from_user_id, messages.to_user_id, 
         messages.body, messages.sent_date,
         ROW_NUMBER() OVER 
         (PARTITION BY messages.from_user_id 
         ORDER BY messages.sent_date DESC) AS message_rank
    FROM 
         messages
    WHERE 
         messages.to_user_id = 31 OR 
         messages.from_user_id = 31
)
SELECT * 
FROM ranked_messages 
WHERE message_rank = 1;

但我也希望每个用户unread_message_count

例如:

select 
     count(*) as unread_message_count 
from 
     messages 
where 
     to_user_id = 31 and 
     is_read = false and 
     from_user_id = 23

应该为向该用户发送消息的每个用户进行计算,反之亦然

如何获得此结果?

2 个答案:

答案 0 :(得分:0)

您可以使用窗口功能。我认为这是逻辑:

WITH ranked_messages AS (
    SELECT m.from_user_id, m.to_user_id, m.body, m.sent_date,
           SUM(is_read::int) OVER (PARTITION BY from_user_id) as cnt
           ROW_NUMBER() OVER (PARTITION BY m.from_user_id ORDER BY m.sent_date DESC) AS message_rank
    FROM messages m
    WHERE 31 IN (m.to_user_id, m.from_user_id)
)
SELECT *
FROM ranked_messages
WHERE message_rank = 1;

答案 1 :(得分:0)

您可以将计数包含为嵌套查询:

WITH ranked_messages AS (
    SELECT messages.from_user_id, messages.to_user_id, messages.body, messages.sent_date,
        select count(*) as unread_message_count from messages where (to_user_id = 31 or from_user_id = 31) and is_read = false,
        ROW_NUMBER() OVER (PARTITION BY messages.from_user_id ORDER BY messages.sent_date DESC) AS message_rank
    FROM messages
    WHERE messages.to_user_id = 31 OR messages.from_user_id = 31
)
SELECT * FROM ranked_messages WHERE message_rank = 1;