4

我有一个用于更新软件包的元数据表。该表有列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)
  );

这有效,但感觉不对。如果我想过滤更多名称,我必须多次复制整个子查询。有一个更好的方法吗?

4

3 回答 3

5
select distinct on (name) id, name, version
from metadata
where name in ('foo', 'bar')
order by name, version desc
于 2013-04-20T11:43:46.003 回答
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
    );

注意:我替换namezname,因为它或多或少是 postgresql 中的一个关键字。

于 2013-04-20T11:44:29.567 回答
2

重读Q后更新:

我想选择名称是某个给定名称列表之一的所有行,并且版本是具有该名称的所有行的最大值。

如果可能存在关联(每个 具有最大版本的多行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;
于 2013-04-20T11:48:15.050 回答