仅选择具有最大列值的行的SQL查询
P粉662614213
P粉662614213 2023-08-21 14:17:15
0
2
393
<p>我有一个文档表(这里是简化版本):</p> <table class="s-table"> <thead> <tr> <th>id</th> <th>rev</th> <th>content</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>1</td> <td>...</td> </tr> <tr> <td>2</td> <td>1</td> <td>...</td> </tr> <tr> <td>1</td> <td>2</td> <td>...</td> </tr> <tr> <td>1</td> <td>3</td> <td>...</td> </tr> </tbody> </table> <p>如何选择每个id的一行,并且只选择最大的rev?</p><p> 根据上述数据,结果应该包含两行:<code>[1, 3, ...]</code> 和 <code>[2, 1, ..]</code>。我正在使用<strong><em>MySQL</em></strong>。</p> <p>目前,我在<code>while</code>循环中使用检查来检测和覆盖结果集中的旧rev。但是这是实现结果的唯一方法吗?难道没有<strong>SQL</strong>的解决方案吗?</p>
P粉662614213
P粉662614213

全部回复(2)
P粉909476457

我更喜欢尽可能少使用代码...

你可以使用IN来实现 试试这个:

SELECT * 
FROM t1 WHERE (id,rev) IN 
( SELECT id, MAX(rev)
  FROM t1
  GROUP BY id
)

在我看来,这样更简单... 更容易阅读和维护。

P粉287345251

乍一看...

你只需要使用带有MAX聚合函数的GROUP BY子句:

SELECT id, MAX(rev)
FROM YourTable
GROUP BY id

事情从来都不会那么简单,是吧?

我刚刚注意到你还需要content列。

这是SQL中一个非常常见的问题:根据某个分组标识符找到某列中具有最大值的整行数据。在我的职业生涯中,我听到了很多这样的问题。实际上,在我目前的工作技术面试中,这是我回答过的问题之一。

这个问题实际上非常常见,以至于Stack Overflow社区专门创建了一个标签来处理这类问题:

基本上,你有两种方法来解决这个问题:

使用简单的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上进行。然后,有两个巧妙的步骤:

  1. 第二个连接条件是左侧值小于右侧值
  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-identifier有两行具有max-value-in-group,那么这两种方法都会将这两行都包含在结果中。

这两种方法都与SQL ANSI兼容,因此无论你喜欢的RDBMS是什么“风格”,都可以使用。

这两种方法在性能上也都友好,但是你的实际情况可能会有所不同(RDBMS、数据库结构、索引等)。所以当你选择其中一种方法时,请进行基准测试。并确保选择对你来说最有意义的方法。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板