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-identifiermax-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个聪明的动作:

  • 第二个连接条件是左侧值小于右侧值
  • 当您执行第1步时,实际上具有最大值的行将在右侧具有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-identifiermax-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

    上一篇: SQL select only rows with max value on a column

    下一篇: How to select the nth row in a SQL database table?