如何在 MySQL 查询中过滤少量重复项

How can i filter few repeatation in MySQL Query

我有一个 mysql table 如下所示。它用于存储带有版本控制的文档。

我想要 select 最新的 docid(具有最高的主要版本和次要版本)。它将消除所有相同的文档 ID,只获取具有最高 major_version 和 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;

在 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

在早期版本中,您可以使用相关子查询进行过滤。假设您在 table 列中有一个主键,例如 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)
        )
)