我有一个如下的mysql表。它用于存储带有版本控制的文档。
我想选择最新的docid(带有主要的主要版本和次要版本)。它将消除所有相同的文档ID,仅获取具有major_version和minor_version最高的文档。所以我想要如下结果。
在MySQL 8.0中,您可以使用row_number()
进行过滤:
select *
from (
select
t.*,
row_number() over(partition by id, docid order by major_version, minor_version) rn
from mytable t
) t
where rn = 1
在早期版本中,您可以使用相关子查询进行过滤。假设您在表中有一个主键,例如列pk
,则可以执行以下操作:
select t.*
from mytable t
where t.pk = (
select t1.pk
from mytable t1
where t1.id = t.id and t1.docid = t.docid
order by t1.major_version desc, t1.minor_version desc
limit 1
)
出于性能考虑,请考虑使用(id, docid, major_version, minor_version)
上的索引。
[没有可以用作主键的唯一列,它要复杂一些。一种方法是使用not exists
:
select t.*
from mytable t
where not exists (
select 1
from mytable t1
where
t1.id = t.id
and t1.docid = t.docid
and (
t1.major_version > t.major_version
or (t1.major_version = t.major_version and t1.minor_version > t.minor_version)
)
)
一种方法使用row_number()
:
select t.*
from (select t.*,
row_number() over (partition by docid order by major_version desc, minor_version desc) as seqnum
from t
) t
where seqnum = 1;
这在早期版本中很痛苦。可能最简单,最有效的方法是使用变量:
select t.*
from (select t.*,
(@rn := if(@d = docid, @rn + 1,
if(@d := docid, 1, 1)
)
) as rn
from (select t.*
from t
order by docid, major_version desc, minor_version desc
) t cross join
(select @rn := 0, @d := '') params
) t
where rn = 1;
您可以使用相关 subquery
:
select t.*
from table t
where (t.major_version, t.minor_version) in (select max(t1.major_version), max(t1.minor_version)
from table t1
where t1.docid = t.docid
);