Как удалить все строки по группам, кроме первой и последней в SQL Server? - PullRequest
3 голосов
/ 02 ноября 2019

У меня есть такие данные

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

Мне нужен запрос, который удалит все строки по группе AuthorId, если их больше 2, кроме первой и последней.

Например, в приведенных выше данных, вторая строка должна быть удалена, потому что для AuthorId = 2 у меня есть 3 строки, но для AuthorId = 3 ничего не будет удалено

Ответы [ 5 ]

3 голосов
/ 02 ноября 2019

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
1 голос
/ 02 ноября 2019

Попробуйте,

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
1 голос
/ 02 ноября 2019

Вы можете попробовать это:

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
1 голос
/ 02 ноября 2019

С 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
  )

См. Демоверсию . Результаты:

Id  Name    AuthorId
1   AAA     2
3   CCC     2
4   DDD     3
5   EEE     3
1 голос
/ 02 ноября 2019

Вы можете попробовать использовать объединение для минимального и максимального идентификатора, а НЕ в результате для этого подзапроса

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 

)
...