我有一个数据库表,如下所示:
id version_id field1 field2
1 1 texta text1
1 2 textb text2
2 1 textc text3
2 2 textd text4
2 3 texte text5
如果您没有计算出来,它包含一行的多个版本,然后是一些文本数据。
我想要查询它并返回每个id的最高编号的版本。(所以只有上面的第二行和最后一行)。
我试过在使用group by的同时按version_id DESC排序--但它似乎是在分组后排序的,所以这不起作用。
有人有什么想法吗?我不敢相信这件事做不到!
更新:
想一想,这是可行的,但使用子查询:
SELECT *
FROM (SELECT * FROM table ORDER BY version_id DESC) t1
GROUP BY t1.id
发布于 2009-02-11 15:09:43
这称为选择列的分组最大值。Here are several different approaches for mysql.
下面是我会怎么做:
SELECT *
FROM (SELECT id, max(version_id) as version_id FROM table GROUP BY id) t1
INNER JOIN table t2 on t2.id=t1.id and t1.version_id=t2.version_id
虽然mysql将在内存中为子查询创建一个临时表,但这将是相对有效的。我假设您已经在这个表的(id,version_id)上有一个索引。
对于这类问题,或多或少必须使用子查询(semi-joins是另一个例子),这是SQL的一个缺点。
子查询在mysql中没有得到很好的优化,但不相关的子查询并不是那么糟糕,只要它们不是太大以至于它们会被写到磁盘上而不是内存中。假设在这个查询中只有两个int,那么在此之前的子查询可能有数百万行,但是第一个查询中的select *子查询可能很快就会遇到这个问题。
发布于 2009-02-11 15:09:55
我想这样就可以了,不过不确定是最好的还是最快的。
SELECT * FROM table
WHERE (id, version_id) IN
(SELECT id, MAX(version_id) FROM table GROUP BY id)
发布于 2009-02-11 15:29:29
SELECT id, version_id, field1, field2
FROM (
SELECT @prev = id AS st, (@prev := id), m.*
FROM (
(SELECT @prev := NULL) p,
(
SELECT *
FROM mytable
ORDER BY
id DESC, version_id DESC
) m
) m2
WHERE NOT IFNULL(st, FALSE);
无子查询,如果你有一个UNIQUE INDEX ON MYTABLE (id, version_id)
(我认为你应该这样做),只需传递一次
https://stackoverflow.com/questions/537223
复制相似问题