如何在 postgresql 的单个查询中 select 行和计数行?
How select a row and count row in single query in postgresql?
我在 postgresql 中有一个 table 如下:
id | chat_id | content | time | read_times
----+---------+-----------+------+-------------------------------------------------------------------------
1 | chat_10 | content_1 | t1 | [{"username": "user1", "time": 123}, {"username": "user2", "time": 111}]
2 | chat_10 | content_2 | t2 | [{"username": "user2", "time": 1235}]
3 | chat_10 | content_3 | t3 | []
4 | chat_11 | content_4 | t4 | [{"username": "user1", "time": 125}, {"username": "user3", "time": 121}]
5 | chat_11 | content_5 | t5 | [{"username": "user1", "time": 126}, {"username": "user3", "time": 127}]
注意:t1 < t2 < t3 < t4 < t5
每个用户阅读一条消息后,我们将其注册在read_times
列(user2
在时间1235
阅读了id为2
的消息),现在我要获取带有未读计数聊天的用户聊天列表。 user1
结果如下:
chat_id | content | unread_count
--------+-----------+--------------
chat_10 | content_3 | 2
chat_11 | content_5 | 0
注意: unread_count
是用户未在 caht_id
.
中阅读的消息数
是否可以一次查询?
首先,您必须使用 json_array_elements()
函数提取每个 chat_id
和 content
的用户名,并使用 FIRST_VALUE()
window 函数获取最后一个 content
每个 chat_id
.
然后将SUM()
window函数与MAX()
聚合函数聚合合并,得到列unread_count
:
WITH cte AS (
SELECT t.chat_id, t.content,
FIRST_VALUE(t.content) OVER (PARTITION BY t.chat_id ORDER BY t.time DESC) last_content,
(r->>'username') username
FROM tablename t LEFT JOIN json_array_elements(read_times::json) r ON true
)
SELECT DISTINCT c.chat_id, MAX(c.last_content) "content",
SUM((MAX((COALESCE(username, '') = 'user1')::int) = 0)::int) OVER (PARTITION BY c.chat_id) unread_count
FROM cte c
GROUP BY c.chat_id, c.content
ORDER BY c.chat_id
参见demo。
我在 postgresql 中有一个 table 如下:
id | chat_id | content | time | read_times
----+---------+-----------+------+-------------------------------------------------------------------------
1 | chat_10 | content_1 | t1 | [{"username": "user1", "time": 123}, {"username": "user2", "time": 111}]
2 | chat_10 | content_2 | t2 | [{"username": "user2", "time": 1235}]
3 | chat_10 | content_3 | t3 | []
4 | chat_11 | content_4 | t4 | [{"username": "user1", "time": 125}, {"username": "user3", "time": 121}]
5 | chat_11 | content_5 | t5 | [{"username": "user1", "time": 126}, {"username": "user3", "time": 127}]
注意:t1 < t2 < t3 < t4 < t5
每个用户阅读一条消息后,我们将其注册在read_times
列(user2
在时间1235
阅读了id为2
的消息),现在我要获取带有未读计数聊天的用户聊天列表。 user1
结果如下:
chat_id | content | unread_count
--------+-----------+--------------
chat_10 | content_3 | 2
chat_11 | content_5 | 0
注意: unread_count
是用户未在 caht_id
.
是否可以一次查询?
首先,您必须使用 json_array_elements()
函数提取每个 chat_id
和 content
的用户名,并使用 FIRST_VALUE()
window 函数获取最后一个 content
每个 chat_id
.
然后将SUM()
window函数与MAX()
聚合函数聚合合并,得到列unread_count
:
WITH cte AS (
SELECT t.chat_id, t.content,
FIRST_VALUE(t.content) OVER (PARTITION BY t.chat_id ORDER BY t.time DESC) last_content,
(r->>'username') username
FROM tablename t LEFT JOIN json_array_elements(read_times::json) r ON true
)
SELECT DISTINCT c.chat_id, MAX(c.last_content) "content",
SUM((MAX((COALESCE(username, '') = 'user1')::int) = 0)::int) OVER (PARTITION BY c.chat_id) unread_count
FROM cte c
GROUP BY c.chat_id, c.content
ORDER BY c.chat_id
参见demo。