Sql 选择满足某些条件且在某列中具有最大值的行
我有一个元数据表,用于更新软件包。该表包含列id、名称、版本。我想选择所有行,其中名称是某个给定名称列表中的一个,并且版本是具有该名称的所有行的最大值 例如,鉴于这些记录:Sql 选择满足某些条件且在某列中具有最大值的行,sql,postgresql,greatest-n-per-group,Sql,Postgresql,Greatest N Per Group,我有一个元数据表,用于更新软件包。该表包含列id、名称、版本。我想选择所有行,其中名称是某个给定名称列表中的一个,并且版本是具有该名称的所有行的最大值 例如,鉴于这些记录: +----+------+---------+ | id | name | version | +----+------+---------+ | 1 | foo | 1 | | 2 | foo | 2 | | 3 | bar | 4 | | 4 | bar | 5
+----+------+---------+
| 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 |
+----+------+---------+
到目前为止,我想到的是使用嵌套查询:
选择*
来自更新
哪里
选择id中的id
来自更新
其中name='foo'
按版本说明订购
限制1
或
选择id中的id
来自更新
其中name='bar'
按版本说明订购
限制1
;
这是可行的,但感觉不对。如果我想过滤更多的名称,我必须多次复制整个子查询。有更好的方法吗?不存在是避免不需要的次优元组的一种方法:
select distinct on (name) id, name, version
from metadata
where name in ('foo', 'bar')
order by name, version desc
注意:我用zname替换了name,因为它或多或少是postgresql中的一个关键字。重新阅读Q: 我想选择名称为某个给定列表之一的所有行 的名称,并且版本是具有该名称的所有行的最大值 如果每个名称可以有多个具有最大版本的行,则可以在子查询中使用window函数。需要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;
名称是,但使用它作为标识符仍然是不好的做法,因为它不是描述性的。我认为它在旧版本中被用作表名和列名的类型名。但也许我只是想在所有东西的前面加上一个z…而且,更重要的是,我认为这个查询是不正确的,就像@Clodoaldo的查询一样。它获取每个名称的最大版本,而不是所有行的最大版本。OQ中的示例所需输出确实表明OP需要每个名称的最大版本。不确定,虽然OQ有WHERE子查询或子查询,但她没有提到在ties的情况下该怎么做。是的,SQL很简单:一旦你掌握了语法,一切都变成了数据建模问题。我非常喜欢DISTINCT ON,但它不是查找所有行(可能包括重复名称)的正确工具。更重要的是:这将检索一行,其中通过WHERE子句的每个名称的最大版本,这与问题要求的AIUI略有不同。这似乎是我想要的,并且看起来是迄今为止所有答案中最简单的,所以我接受它。谢谢@亚当:重读后,我发现我似乎误解了你的问题。@erwin:可能是我的问题措辞不正确。对于每个名称,我希望该行具有该名称的所有行的最大版本。对于每个名称,我只需要一行。这个答案不是这样吗?在我的例子中,名称、版本总是唯一的。我应该把这一点放在原来的问题中。我的回答如下:
SELECT *
FROM (
SELECT *, rank() OVER (PARTITION BY name ORDER BY version DESC) AS rnk
FROM updates
WHERE name IN ('foo', 'bar')
)
WHERE rnk = 1;