Эффективный способ получить только самые последние данные и удалить остальные из таблицы

#sql #sql-server #datetime #greatest-n-per-group #sql-delete

#sql #sql-сервер #дата и время #наибольшее число на группу #sql-удалить

Вопрос:

Я пытаюсь найти самый быстрый способ удалить данные из моей таблицы. Моя логика заключается в том, чтобы иметь только последние 2 дня данных в Table1 для данного Lot_ID, а ID является уникальным первичным ключом в таблице.

Моих данных немного, но для выполнения приведенного ниже запроса мне все равно требуется около 8-9 минут.

 WITH CTE AS
(
 select t.ID
from (select t1.*,
             DENSE_RANK() over (partition by Lot_ID order by TRY_CONVERT(DATE, DATEADD(second, t1.starttime, '19700101') )           
              desc) as seqnum
      from  Table1 t1
     ) t
where seqnum >2
)
DELETE Table1 WHERE EXISTS(select 1 from CTE where CTE.ID = Table1.ID )
 

Есть ли самый быстрый или лучший подход для этого?

Комментарии:

1. временные таблицы могут сделать это за вас (с периодом хранения для таблицы истории)

Ответ №1:

Вы можете попробовать удалить непосредственно из cte, а не повторно открывать таблицу:

 with cte as(
    select dense_rank() over (
        partition by lot_id 
        order by try_convert(date, dateadd(second, t1.starttime, '19700101')) desc
    ) as seqnum
    from  table1 t1
)
delete from cte where seqnum > 2
 

Ваш запрос предполагает, что startime это временная метка эпохи (то есть int тип данных), поэтому другой возможной оптимизацией является использование арифметики, а не преобразование даты:

 with cte as(
    select dense_rank() over (
        partition by lot_id 
        order by t1.starttime / 60 / 60 / 24 desc
    ) as seqnum
    from  table1 t1
)
delete from cte where seqnum > 2
 

Если ничего из этого не помогает, тогда вы можете рассмотреть возможность изменения логики: то есть перемещения записей, которые вы хотите сохранить, во временную таблицу, затем настройки и повторного заполнения исходной таблицы.

Комментарии:

1. Спасибо @GMB. Похоже, что в моем случае правильнее всего использовать обратную логику, поскольку мне нужно найти самый быстрый способ выполнить это. Вместо того, чтобы усекать, я удалил свою основную таблицу и переименовал временную таблицу с помощью cte как (select t1.*, DENSE_RANK() over (partition by Lot_ID order by TRY_CONVERT(DATE, DATEADD(second, t1.starttime, ‘19700101’) ) desc) как seqnum из Table1 t1 ) select *в Test1 из cte, где seqnum <=2; — удалить таблицу Table1; EXEC sp_rename ‘dbo.Test1’, ‘Table1’;