Наиболее читаемый способ - это, вероятно, то, что вы написали. Но это может быть очень расточительным в зависимости от различных факторов. В частности, если на process_date
нет индекса, он, вероятно, должен выполнить 2 полных сканирования таблицы.
Сложность в написании чего-то более простого и эффективного состоит в том, что любое представление таблицы, включающее ранжирование или упорядочение, также не допускает изменений.
Вот еще один альтернативный подход к нему, использующий PL / SQL, который, вероятно, будет более эффективным в некоторых случаях, но явно менее читабельным.
DECLARE
CURSOR delete_cur IS
SELECT /*+ FIRST_ROWS(1) */
NULL
FROM daily_statistics
ORDER BY process_date DESC
FOR UPDATE;
trash CHAR(1);
BEGIN
OPEN delete_cur;
FETCH delete_cur INTO trash;
IF delete_cur%FOUND THEN
DELETE FROM daily_statistics WHERE CURRENT OF delete_cur;
END IF;
CLOSE delete_cur;
END;
/
Также обратите внимание, что это может привести к другим результатам из вашего оператора, если может быть несколько строк с одинаковым значением process_date
. Для обработки дубликатов требуется немного больше сложности:
DECLARE
CURSOR delete_cur IS
SELECT /*+ FIRST_ROWS(1) */
process_date
FROM daily_statistics
ORDER BY process_date DESC
FOR UPDATE;
del_date DATE;
next_date DATE;
BEGIN
OPEN delete_cur;
FETCH delete_cur INTO del_date;
IF delete_cur%FOUND THEN
DELETE FROM daily_statistics WHERE CURRENT OF delete_cur;
END IF;
LOOP
FETCH delete_cur INTO next_date;
EXIT WHEN delete_cur%NOTFOUND OR next_date <> del_date;
DELETE FROM daily_statistics WHERE CURRENT OF delete_cur;
END LOOP;
CLOSE delete_cur;
END;
/