我如何过滤MySQL查询中的少量重复

问题描述 投票:-2回答:2

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

enter image description here

我想选择最新的docid(带有主要的主要版本和次要版本)。它将消除所有相同的文档ID,仅获取具有major_version和minor_version最高的文档。所以我想要如下结果。

enter image description here

mysql sql greatest-n-per-group
2个回答
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

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

0
投票

一种方法使用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;

0
投票

您可以使用相关 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 
                                            );
© www.soinside.com 2019 - 2024. All rights reserved.