Удалить регистры с номером больше, чем указано для каждой группы, полученной из sql - PullRequest
0 голосов
/ 29 февраля 2020

У меня есть таблица людей с их комментариями в блоге. Мне нужно оставить последние 10 комментариев для каждого человека в таблице и удалить старые. Допустим, столбцы:

  • personId
  • commentId
  • dateFromComment

Я знаю, как это сделать с несколькими запросами, но не только с одним запросом (разрешены любые подзапросы) и для anyDatabase

С:

select personId from PeopleComments 
group by personId
having count(*) >10 

Я бы получил идентификаторы людей, которые имеют более 10 комментариев, но я не знаю, как получить комментарии Идентификаторы оттуда и удалите их

Спасибо!

Ответы [ 2 ]

1 голос
/ 29 февраля 2020

В моем другом ответе СУБД должна найти и сосчитать строки для каждой строки в таблице. Это может быть медленным. Было бы лучше найти все строки, которые мы хотим сохранить один раз, а затем удалить остальные. Отсюда и этот дополнительный ответ.

Следующее работает для Oracle с версии 12 c:

delete from peoplecomments
where rowid not in
(
  select rowid
  from peoplecomments
  order by row_number() over (partition by personid order by datefromcomment desc)
  fetch first 10 rows with ties
);

Кроме ROWID это стандарт SQL.

В других СУБД, которые поддерживают оконные функции и FETCH WITH TIES:

  • Если ваша таблица имеет первичный ключ из одной колонки, вы замените ROWID ей.
  • Если ваша таблица имеет составной первичный ключ, вы должны использовать where (col1, col2) not in (select col1, col2 ...), если ваша СУБД поддерживает этот синтаксис.
1 голос
/ 29 февраля 2020

Вам нужен коррелированный подзапрос с подсчетом следующих комментариев:

delete from peoplecomments pc
where
(
  select count(*)
  from peoplecomments pc2
  where pc2.personid = pc.personid
  and pc2.datefromcomment > pc.datefromcomment
) >= 10; -- at least 10 newer comments for the person

Кстати: хотя кажется, что мы могли бы просто нумеровать наши строки и соответственно удалять их с помощью

delete from
(
  select
    pc.*, row_number() over (partition by personid order by datefromcomment desc) as rn
  from peoplecomments pc
)
where rn > 10;

Oracle, это не позволяет и дает нам ORA-01732: data manipulation operation not legal on this view.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...