Это можно сделать с помощью оконных функций min
и max
. Пустое предложение over()
вычисляет агрегацию для всех значений в столбце. Так как оконные функции не являются агрегатными функциями, нет необходимости в group by
.
select ID,
(count1-min(count1) over())/(max(count1) over()-min(count1) over()),
(count2-min(count2) over())/(max(count2) over() -min(count2) over())
from table1
Если бы это просто кажется неэффективным, я удостоверился бы, что это неэффективно, прежде чем я начну рявкать неправильное дерево.
Измерьте время, использование CPU, диск ввод-вывод, и т.д. чтобы видеть, как хорошо это работает. Я думаю, что Вы найдете, что это работает лучше, чем Вы думаете.
DECLARE @limit INT
SELECT @limit = min(id) FROM
(SELECT TOP 20000 id FROM your_table ORDER BY id DESC)x
DELETE FROM your_table where id < @limit
Точка должна была избежать вложенного запроса, который я могу или не могу быть оптимизирован (извините не sql гуру.)
Конечно, Ваш пробег будет варьироваться - Это будет зависеть от того, сколько реальных записей Вы соскабливаете нижнюю часть этой таблицы, но вот альтернатива.
Примечание стороны: Так как у Вас есть поле "Date_Added", это было бы достойно рассмотрения для простого хранения даты и времени последнего выполнения и использования этим в Вашем где пункт для фильтрации записей, которые будут удалены? Теперь, вместо 20 000 записей, позвольте X количеств дней в журнале... Просто мысль...
- Получите учет, который мы хотим ВЕСТИ во временный файл.
- Можно классифицировать хранителей однако, Вы желаете.
select top 20000 * into #myTempTable from MyTable ORDER BY DateAdded DESC
- Используя усеченный не повреждает наш файл журнала и использует меньше sys ресурсов...
truncate table MyTable
- Возвратите наш 'ведомый' учет в сгиб...
- Это предполагает, что Вы НЕ используете столбец идентификационных данных - если Вы, Вы должны
- укажите имена полей вместо того, чтобы использовать '*' и сделайте что-то как
- IDENTITY_INSERT MyTable НАБОРА НА
- вставьте в field1 выбора MyTable, field2, field3 от #myTempTable
- (Я думаю правильно),
insert into MyTable select * from #myTempTable
- будьте добропорядочным гражданином.
drop table #myTempTable
Надежда это помогает-
Вы подвергаете сомнению, подразумевает, что Вы обрезаете для получения лучшей дневной производительности от таблицы. Вы получаете сканирования таблицы на дневных запросах? Разве лучшие индексы не были бы ответом? Или Вы находитесь в ситуации, где Вы застреваете с "дрянной схемой"?
Или действительно имеет некоторая действительно странная ситуация, где действительно необходимо произвести чистку старых записей? Действительно ли 20,000 надежное число? Или дата и время могла работать? Затем и индекс на столбце даты и времени сделал бы обрезку немного легче.
Конечно, это - главный случай для оборачивания в процедуру и использования двух sql операторов - первое, чтобы выбрать последний идентификатор и вычесть 20,000, затем второе для удаления всех строк с идентификатором ниже, чем это.
Однако это действительно на первый взгляд кажется, что Вы собираетесь закончить с большой фрагментацией, идущей с этим подходом, и это могло бы быть хорошим аргументом для того, чтобы составить новую таблицу, вставив последние 20 000 записей в него, удалив старый и переименовав новое. Это могло бы даже быть стоящее помещение таблицы в другой базе данных и создании представления от Вашей основной базы данных для облегчения доступа. Самостоятельно я обычно склонен делать это с таблицами, используемыми для загрузки данных и аудита.
Очень трудно сказать, не зная Ваших фактических объемов данных и поведения, но могло случиться так, что глобально Ваша неэффективность возникнет больше из этого, чем удалить метод, который Вы используете. Если Вы только собираете тысячу или меньше записей в день затем, удаление, вероятно, в порядке объединено с выполнением плана технического обслуживания оптимизации данных, но больше и я посмотрел бы на более решительный подход.