RaR*_*RaR 10 postgresql greatest-n-per-group
我有两个表叫做record和record_history。对于每条记录,可能有多个历史记录。它们可以通过id和 连接record_id。我想record用最近的record_history数据获取所有的条目。我已经创建了这样的查询,
SELECT rec.id, rec.name, rech1.data AS last_history_data
FROM record rec
LEFT OUTER JOIN record_history rech1 ON (rec.id = rech1.record_id)
LEFT OUTER JOIN record_history rech2 ON (rec.id = rech2.record_id AND rech2.ts > rech1.ts)
WHERE rech2.id IS NULL
ORDER BY rec.id DESC
Run Code Online (Sandbox Code Playgroud)
在这里,我通过ts. 只要没有重复的ts条目,这就会起作用。如果最近的时间戳在 中重复record_history,则此查询将返回多于一行的记录。我们如何在左连接上应用限制来限制重复行?
ype*_*eᵀᴹ 14
除非您使用的是非常旧版本的 Postgres,否则您不需要双重连接。您可以通过使用LATERALjoin获得相同的结果。
通过添加除rec.id = rech2.record_id. 使用LATERALjoin 方法,LIMIT 无论如何都要避免它。横向子查询只能返回 1 行。我们可以添加第二个条件,以便选择是确定性的(来自具有相同时间戳的两行或更多行):
SELECT rec.id, rec.name, rech.data AS last_history_data
FROM record AS rec
LEFT OUTER JOIN LATERAL
( SELECT rech.data
FROM record_history AS rech
WHERE rec.id = rech.record_id
ORDER BY rech.ts DESC
-- ,rech.id DESC -- optional
LIMIT 1
) AS rech
ON TRUE
ORDER BY rec.id DESC ;
Run Code Online (Sandbox Code Playgroud)
关于如何使用原始方法(2 个连接和IS NULL检查)执行此操作,您可以更改ON条件 - 假设id历史表中有一个列,以便(id)或至少(ts, id)是唯一的:
LEFT OUTER JOIN record_history rech2
ON rec.id = rech2.record_id
AND (rech2.ts > rech1.ts OR rech2.ts = rech1.ts AND rech2.id > rech1.id)
Run Code Online (Sandbox Code Playgroud)
顺便说一下,您可以替换第二个LEFT连接并IS NULL使用NOT EXISTS具有相同结果和可能相似效率的子查询进行检查(或者甚至使用NOT IN子查询,尽管这需要额外注意可空列,不推荐)。
| 归档时间: |
|
| 查看次数: |
32234 次 |
| 最近记录: |