在我正在使用的一个应用程序中,我的Postgres数据库中有一个 comments 表,它可以简化为如下所示:

+----+-----------+-----------------+---------------------+
| id | parent_id | group_member_id |     created_at      |
+----+-----------+-----------------+---------------------+
| 1  | NULL      | 1               | 2023-08-01 12:00:00 |
| 2  | NULL      | 2               | 2023-08-01 12:00:01 |
| 3  | NULL      | 2               | 2023-08-01 12:00:02 |
| 4  | 3         | 1               | 2023-08-01 12:00:03 |
| 5  | 2         | 1               | 2023-08-01 12:00:04 |
| 5  | 1         | 1               | 2023-08-01 12:00:05 |
| 6  | 2         | 2               | 2023-08-01 12:00:06 |
| 7  | 2         | 1               | 2023-08-01 12:00:07 |
+----+-----------+-----------------+---------------------+

填充parent_id列时,它会引用COMMENT表中的另一行.这将建立父/子关系.换句话说,一条 comments 可以有其他回复的 comments .任何家长的 comments 都可以有很多回复.就这款应用程序而言, comments 父/子关系只有一个级别.

还有一个Group Members表,由Comments表通过外键引用.它代表每个 comments 的作者,可以简化为:

+----+---------------+
| id |     name      |
+----+---------------+
|  1 | Johnny Tables |
|  2 | Susan Select  |
+----+---------------+

对于任何给定的组成员,我想要找到他们回复的最新不同的根 comments ,按照他们回复的顺序.例如,Johnny Tables(Id 1)将得到:

+----+-----------+-----------------+---------------------+
| id | parent_id | group_member_id |     created_at      |
+----+-----------+-----------------+---------------------+
|  2 | NULL      |               2 | 2023-08-01 12:00:01 |
|  1 | NULL      |               1 | 2023-08-01 12:00:00 |
|  3 | NULL      |               2 | 2023-08-01 12:00:02 |
+----+-----------+-----------------+---------------------+

Susan Select(ID 2)将获得:

+----+-----------+-----------------+---------------------+
| id | parent_id | group_member_id |     created_at      |
+----+-----------+-----------------+---------------------+
|  2 | NULL      |               2 | 2023-08-01 12:00:01 |
+----+-----------+-----------------+---------------------+

Here is a fiddle,它用示例数据设置表 struct .

我try 了使用子查询以及DISTINCTORDER BY的各种咒语,但我遗漏了一些东西.例如,使用下面的查询,我似乎得到了正确的答复,但实际上并没有按created_at日期进行排序.它们是按升序parent_id排序的

SELECT DISTINCT ON (parent_id)
    parent_id,
    created_at
FROM
    comments
WHERE
    comments.group_member_id = 1
    AND comments.parent_id IS NOT NULL
ORDER BY
    comments.parent_id,
    comments.created_at DESC

一旦我有了它,我就不太知道如何利用它来获得根 comments ,并将它们保持在回复的时间顺序上.我遗漏了什么?

Note: While I'm asking for general SQL guidance here, since the app I'm working on is a Rails app, an Active Record or Arel interpretation would also be welcome.

新增EDIT:张样表和预期结果.

推荐答案

您的小提琴数据看起来将parent_id列和group_member_id列颠倒了.

由于根/子注释层次 struct 中只有一个级别,因此您的查询过于复杂.

这是一个简单的group by,在根注释中加入了一个连接:

select gm.name, r.id, r.group_member_id, r.parent_id, r.created_at,
       max(c.created_at) as last_reply_at
  from comments c
       join group_members gm on gm.id = c.group_member_id
       join comments r on r.id = c.parent_id
 group by gm.name, r.id, r.group_member_id, r.parent_id, r.created_at
 order by gm.name, max(c.created_at) desc;

更新fiddle

Sql相关问答推荐

如何并行SELECT和RESET?

如何转换和汇总行数

更新在两个或多个面中具有交点的面

PostgreSQL:使用JSONB中的字段使用jsonb_to_Records()填充记录

SQL:如何将相应位置的两个数组中的元素组合在一起

查询每周数据(周一至周日),避免年度日期重叠

来自按PostgreSQL分组的最小日期

带日期函数的复合索引不允许只扫描索引吗?

使用拆分器将已分组的不同值连接在一起

显示十进制列,但尽可能显示为整数

在 Postgres 中将结果按几十年划分

Select 一个非零值减少重复

具有分组条件的不同计数 (DAX)

在特定条件下使用 LAG,确定要采用什么 LAG 值?

INSERT INTO 语法

基于 Snowflake 的最大值创建新列

postgres按组消除分区中的NULLS

连续期间的缺口

创建一个将层次 struct 级别放入列中的查询

Snowflake SQL group-by 的行为不同,具体取决于列是按位置引用还是按别名引用