SQL只选择列上具有最大值的行
我有这张表格(这里是简体版):
+------+-------+--------------------------------------+
| id | rev | content |
+------+-------+--------------------------------------+
| 1 | 1 | ... |
| 2 | 1 | ... |
| 1 | 2 | ... |
| 1 | 3 | ... |
+------+-------+--------------------------------------+
我如何为每个ID选择一行而只选择最大的转速?
通过上述数据,结果应该包含两行: [1, 3, ...]
和[2, 1, ..]
。 我正在使用MySQL 。
目前我在while
循环中使用检查来检测并覆盖结果集中的旧版本。 但是,这是实现结果的唯一方法吗? 没有SQL解决方案吗?
更新
正如答案所示,有一个SQL解决方案,这里是一个sqlfiddle演示。
更新2
我注意到在添加上面的sqlfiddle之后,问题被提高的速率已经超过了答案的满意率。 这并非意图! 小提琴基于答案,特别是被接受的答案。
乍一看...
所有你需要的是一个带有MAX
聚合函数的GROUP BY
子句:
SELECT id, MAX(rev)
FROM YourTable
GROUP BY id
它从来没有那么简单,是吗?
我只是注意到你也需要content
列。
这是SQL中的一个非常常见的问题:根据某个组标识符找到某列中某些最大值的行的全部数据。 在我的职业生涯中,我听到了很多。 事实上,这是我在当前工作的技术面试中回答的问题之一。
实际上,StackOverflow社区已经创建了一个标签来处理类似这样的问题:最大的每个群组。
基本上,你有两种方法来解决这个问题:
加入简单的group-identifier, max-value-in-group
子查询
在这种方法中,您首先在子查询中找到group-identifier, max-value-in-group
(上面已解决)。 然后,将您的表加入到子查询中,使用group-identifier
和max-value-in-group
上的等式:
SELECT a.id, a.rev, a.contents
FROM YourTable a
INNER JOIN (
SELECT id, MAX(rev) rev
FROM YourTable
GROUP BY id
) b ON a.id = b.id AND a.rev = b.rev
左连接与自我,调整连接条件和过滤器
在这种方法中,您将自己与表连接起来。 平等,当然,在group-identifier
。 然后,2个聪明的动作:
NULL
(这是一个LEFT JOIN
,请记住?)。 然后,我们过滤连接的结果,只显示右侧为NULL
的行。 所以你最终得到:
SELECT a.*
FROM YourTable a
LEFT OUTER JOIN YourTable b
ON a.id = b.id AND a.rev < b.rev
WHERE b.id IS NULL;
结论
两种方法都带来了完全相同的结果。
如果您有两行group-identifier
为max-value-in-group
,那么两个行都将在两种方法的结果中出现。
这两种方法都兼容SQL ANSI,因此,无论其“风味”如何,都可与您最喜爱的RDBMS一起使用。
两种方法都对性能友好,但是您的里程可能会有所不同(RDBMS,数据库结构,索引等)。 所以当你选择一种方法,基准。 并确保你选择对你最有意义的一个。
我的首选是尽可能少使用代码...
你可以使用IN
做到这一点:
SELECT *
FROM t1 WHERE (id,rev) IN
( SELECT id, MAX(rev)
FROM t1
GROUP BY id
)
在我看来,它并不复杂......更易于阅读和维护。
另一个解决方案是使用相关的子查询:
select yt.id, yt.rev, yt.contents
from YourTable yt
where rev =
(select max(rev) from YourTable st where yt.id=st.id)
有一个索引(id,rev)将子查询呈现为一个简单的查找...
以下是与@ AdrianCarneiro的答案(子查询,左连接)中的解决方案进行比较,根据MySQL测量数据和InnoDB表中的约100万条记录,组大小为:1-3。
虽然对于全表扫描来说,子查询/左连接/相关时序彼此相关为6/8/9,当涉及到直接查找或批处理( id in (1,2,3)
)时,子查询比其他(由于重新运行子查询)。 然而,我无法区分左联盟和相关解决方案的速度。
最后一点,作为左连接创建n *(n + 1)/ 2连接,它的性能会受到团队规模的严重影响......
链接地址: http://www.djcxy.com/p/16887.html