【问题标题】:How to delete all rows by group except the first and the last one in SQL Server?如何按组删除除 SQL Server 中的第一行和最后一行之外的所有行?
【发布时间】:2019-11-02 07:36:11
【问题描述】:

我有这样的数据

Id Name AuthorId 
----------------
1  AAA  2
2  BBB  2
3  CCC  2
4  DDD  3
5  EEE  3

如果有超过 2 行,我需要一个查询,该查询将按组 AuthorId 删除所有行,但第一个和最后一个除外。

比如上面的数据,第二行应该删除,因为AuthorId = 2,我有3行,但是AuthorId = 3,什么都不会删除

【问题讨论】:

    标签: sql sql-server group-by sql-delete


    【解决方案1】:

    Row_number() 两次并删除非终端

    delete t
    from (
       select *,
          row_number() over(partition by [AuthorId]  order by [Id]) n1,
          row_number() over(partition by [AuthorId]  order by [Id] desc) n2
       from tablename
    ) t
    where n1 > 1 and n2 > 1
    

    【讨论】:

      【解决方案2】:

      您可以尝试对最小和最大 id 使用联合,而不是在此子查询的结果中

      delete from my_table 
      where id  NOT  IN  (
      
      
          select  min(id) 
          from my_table 
          group by AuthorId 
          union 
          select max(id)
          from my_table 
          group by AuthorId 
      
      )
      

      【讨论】:

      • 只有当组中的项目 >= 2 时才应该发生删除操作的条件,如果我的 Id 是 GUID,该怎么办?
      • 如果您要保存第一条和最后一条记录,则不能使用 count > 2 .. 因为您不知道哪些记录删除...对于 GUID 或 ID,如果是主键 ..是一样的..
      【解决方案3】:

      你可以试试这个:

      Declare @t table (id int,name varchar(50),Authorid int)
      
      insert into @t values (1,'AAA',2)
      insert into @t values (2,'BBB',2)
      insert into @t values (3,'CCC',2)
      insert into @t values (4,'FFF',2)
      insert into @t values (5,'DDD',3)
      insert into @t values (6,'EEE',3)
      ;with cte as
      (
      select * from (
      select *,count(*) over (partition by authorid) cnt from @t
      ) t
      where cnt > 2
      )
      
      delete a from cte b join @t a on a.id=b.id where b.id not in (select min(id) from cte group by Authorid) and b.id not in (select max(id) from cte group by Authorid)
      
      select * from @t
      

      【讨论】:

        【解决方案4】:

        试试这个,

        Declare @Temp_Data table (id int,name varchar(50),Authorid int)
        
        insert into @Temp_Data values (1,'AAA',2)
        insert into @Temp_Data values (2,'BBB',2)
        insert into @Temp_Data values (3,'CCC',2)
        insert into @Temp_Data values (4,'DDD',3)
        insert into @Temp_Data values (5,'EEE',3)
        
        Delete a
        from @Temp_Data as a
        inner join @Temp_Data as b on a.authorid=b.authorid and b.id > a.id
        inner join @Temp_Data as c on a.authorid=c.authorid and c.id < a.id
        
        select * from @Temp_Data
        

        【讨论】:

          【解决方案5】:

          EXISTS:

          delete t
          from tablename t
          where 
            exists (
              select 1 from tablename
              where authorid = t.authorid and id > t.id
            )
            and
            exists (
              select 1 from tablename
              where authorid = t.authorid and id < t.id
            )
          

          请参阅demo
          结果:

          Id  Name    AuthorId
          1   AAA     2
          3   CCC     2
          4   DDD     3
          5   EEE     3
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-01-16
            • 2010-09-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多