Heim > Fragen und Antworten > Hauptteil
Ich habe eine Dokumententabelle (hier eine vereinfachte Version):
id | Weiterleiten | Inhalt |
---|---|---|
1 | 1 | ... |
2 | 1 | ... |
1 | 2 | ... |
1 | 3 | ... |
Wie wähle ich eine Zeile für jede ID aus und wähle nur die größte Rev aus?
Basierend auf den oben genannten Daten sollte das Ergebnis zwei Zeilen enthalten: [1, 3, ...]
和 [2, 1, ..]
. Ich verwende MySQL.
Derzeit verwende ich eine Prüfung in einer while
Schleife, um alte Drehzahlen im Ergebnissatz zu erkennen und zu überschreiben. Aber ist das der einzige Weg, um Ergebnisse zu erzielen? Gibt es keine SQL-Lösung?
P粉7147807682023-09-21 12:21:06
我更喜欢尽可能少使用代码...
你可以使用IN
来实现
试试这个:
SELECT * FROM t1 WHERE (id,rev) IN ( SELECT id, MAX(rev) FROM t1 GROUP BY id )
在我看来,这样更简单...更容易阅读和维护。
P粉3365367062023-09-21 09:25:48
你只需要在GROUP BY
子句中使用MAX
聚合函数:
SELECT id, MAX(rev) FROM YourTable GROUP BY id
我刚刚注意到你还需要content
列。
在SQL中,这是一个非常常见的问题:根据某个分组标识符找到某个列中具有最大值的整行数据。在我的职业生涯中,我听到过很多这样的问题。实际上,在我目前的工作的技术面试中,这是我回答的一个问题。
这个问题实际上非常常见,以至于Stack Overflow社区专门创建了一个标签来处理这类问题:greatest-n-per-group。
基本上,你有两种方法来解决这个问题:
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
中。然后,有两个巧妙的步骤:
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、数据库结构、索引等)。因此,在选择一种方法时,要进行基准测试。确保选择对你来说最有意义的方法。