【问题标题】:How select a row and count row in single query in postgresql?如何在 postgresql 的单个查询中选择一行并计算行数?
【发布时间】:2021-10-02 11:45:39
【问题描述】:

我在 postgresql 中有一个如下表:

 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 中阅读的消息数。

一个查询可以吗?

【问题讨论】:

  • 你能解释一下专栏unread_count吗?
  • 似乎user1 的“未读计数”考虑了任何不包括"username": "user1" 的行。
  • 还不清楚,为什么user1,在chatid 10和内容3中,unread_count是2??

标签: sql postgresql group-by window-functions postgresql-13


【解决方案1】:

首先,您必须使用json_array_elements() 函数和FIRST_VALUE() 窗口函数提取每个chat_idcontent 的用户名,获取每个chat_id 的最后一个content
然后聚合并结合SUM()窗口函数和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

【讨论】:

  • 谢谢,可以选择time等其他栏目吗?
  • @MortezaMalvandi 检查这个:dbfiddle.uk/…
  • 不正确,将id为3的行的时间改为t0
  • @MortezaMalvandi 您的样本数据中没有 t0。查询返回每个chat_id的最大时间。
  • 因为我说选择最后选定行的所有列。我认为必须使用FIRST_VALUE(t.column_name) OVER (PARTITION BY t.chat_id ORDER BY t.time DESC) last_column_name
猜你喜欢
  • 2016-11-01
  • 1970-01-01
  • 2019-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
相关资源
最近更新 更多