我有一个用于更新软件包的元数据表。该表包含id, name, version
列。我想选择名称是某个给定名称列表之一的所有行,并且版本是具有该名称的所有行的最大值。
例如,鉴于这些记录:
+----+------+---------+
| id | name | version |
+----+------+---------+
| 1 | foo | 1 |
| 2 | foo | 2 |
| 3 | bar | 4 |
| 4 | bar | 5 |
+----+------+---------+
任务“给我最高版本的记录”foo“和”bar“,我希望结果如下:
+----+------+---------+
| id | name | version |
+----+------+---------+
| 2 | foo | 2 |
| 4 | bar | 5 |
+----+------+---------+
到目前为止,我提出的是使用嵌套查询:
SELECT *
FROM updates
WHERE (
id IN (SELECT id
FROM updates
WHERE name = 'foo'
ORDER BY version DESC
LIMIT 1)
) OR (
id IN (SELECT id
FROM updates
WHERE name = 'bar'
ORDER BY version DESC
LIMIT 1)
);
这有效,但感觉不对。如果我想过滤更多名称,我必须多次复制整个子查询。有更好的方法吗?
答案 0 :(得分:4)
select distinct on (name) id, name, version
from metadata
where name in ('foo', 'bar')
order by name, version desc
答案 1 :(得分:3)
NOT EXISTS
是一种避免不需要的次优元组的方法:
SELECT *
FROM updates uu
WHERE uu.zname IN ('foo', 'bar')
AND NOT EXISTS (
SELECT *
FROM updates nx
WHERE nx.zname = uu.zanme
AND nx.version > uu.version
);
注意:我已将name
替换为zname
,因为它是或多或少 postgresql中的关键字。
答案 2 :(得分:2)
重新阅读Q后更新:
我想选择所有行,其中名称是某个给定列表之一 名称和版本是具有该名称的所有行的最大值。
如果可以存在tie(多行具有每name
的最大版本),则可以在子查询中使用窗口函数rank()
。需要PostgreSQL 8.4 +。
SELECT *
FROM (
SELECT *, rank() OVER (PARTITION BY name ORDER BY version DESC) AS rnk
FROM updates
WHERE name IN ('foo', 'bar')
)
WHERE rnk = 1;