如何按组删除 SQL 服务器中除第一行和最后一行以外的所有行?

How to delete all rows by group except the first and the last one in SQL Server?

我有这样的数据

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,什么都不会被删除

您可以尝试对最小和最大 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 

)

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

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

你可以试试这个:

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

试试这个,

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