#sql #sql-server-2016
#sql #sql-server-2016
Вопрос:
Рассмотрим следующее определение таблицы:
FooTable
ID int,
TimeStamp datetime,
Data varchar(50)
Я хотел бы сохранить только данные за последние 6 месяцев, но также убедиться, что в таблице хранится не менее 100 строк данных. Как мне это сделать?
Я знаю, как удалить данные возрастом более 6 месяцев:
DELETE
FROM FooTable
WHERE TimeStamp <= DATEADD(MONTH, -6, GETDATE())
Как мне добавить условие сохранения не менее 100 строк данных в таблице (независимо от того, как хранятся данные)?
Спасибо, JohnB
Комментарии:
1. Пожалуйста, пометьте используемую вами СУБД, например, SQL Server 2019
Ответ №1:
Я думаю, вы хотите:
WITH todelete AS (
SELECT f.*,
ROW_NUMBER() OVER (ORDER BY TimeStamp DESC) as seqnum
FROM FooTable
)
DELETE FROM todelete
WHERE seqnum > 100 AND
TimeStamp < DATEADD(MONTH, -6, GETDATE());
При этом удаляются самые старые временные метки, но при этом они удаляются только после 100-й записи.
Ответ №2:
Я полагаю, вы будете использовать этот код в SSMS для очистки данных, поэтому вам будет все равно, включает ли он некоторые переменные.
Итак, мое решение таково:
DECLARE @CURRENT_NO INT
SELECT @CURRENT_NO = COUNT(*) FROM xTable WHERE timstamp < DATEADD(MONTH, -6, GETDATE())
DECLARE @DEL_NO INT
SELECT @DEL_NO = CASE WHEN @CURRENT_NO < 100 THEN 100 ELSE @CURRENT_NO END
DECLARE @DEL_ROW_NO INT
SELECT @DEL_ROW_NO = COUNT(*) @DEL_NO - 100 FROM xTable WHERE timstamp > DATEADD(MONTH, -6, GETDATE())
DELETE TOP (@DEL_ROW_NO) FROM xTable WHERE timstamp < DATEADD(MONTH, -6, GETDATE())
SELECT * FROM xTable
Я протестировал его с помощью приведенного ниже сценария (уменьшенная версия):
CREATE TABLE xTable (timstamp DATETIME, qty INT)
INSERT INTO xTable VALUES
('2020-11-01', 5), ('2020-01-01', 5), ('2020-01-01', 5), ('2020-01-01', 5), ('2020-01-01', 5),
('2020-11-01', 5), ('2020-01-01', 5), ('2020-01-01', 5), ('2020-01-01', 5), ('2020-01-01', 5)
DECLARE @CURRENT_NO INT
SELECT @CURRENT_NO = COUNT(*) FROM xTable WHERE timstamp < DATEADD(MONTH, -6, GETDATE())
DECLARE @DEL_NO INT
SELECT @DEL_NO = CASE WHEN @CURRENT_NO < 5 THEN 5 ELSE @CURRENT_NO END
SELECT @DEL_NO
DECLARE @DEL_ROW_NO INT
SELECT @DEL_ROW_NO = COUNT(*) @DEL_NO - 5 FROM xTable WHERE timstamp > DATEADD(MONTH, -6, GETDATE())
SELECT @DEL_ROW_NO
DELETE TOP (@DEL_ROW_NO) FROM xTable WHERE timstamp < DATEADD(MONTH, -6, GETDATE())
SELECT * FROM xTable
DROP TABLE xTable
и в результате получается :
------------------------- -----
| timstamp | qty |
------------------------- -----
| 2020-11-01 00:00:00.000 | 5 |
| 2020-11-01 00:00:00.000 | 5 |
| 2020-01-01 00:00:00.000 | 5 |
| 2020-01-01 00:00:00.000 | 5 |
| 2020-01-01 00:00:00.000 | 5 |
------------------------- -----