Обновление TOP 10 строк по приоритету в MS SQL: решение
Быстрый ответ
Представлен простой код, позволяющий обновить данные в заданном порядке с помощью Общего Табличного Выражения (CTE):
-- Давайте узнаем о способностях CTE!
WITH CTE AS (
SELECT TOP(5) *
FROM YourTable
WHERE ConditionColumn = 'ConditionValue'
ORDER BY OrderColumn ASC
)
UPDATE CTE
SET UpdateColumn = 'NewValue'
Так, первые 5 записей, отвечающих criteriu ConditionColumn
и отсортированных по OrderColumn
, будут обновлены.
[AsideBanner]
Возможности и использование подзапросов
Подзапросы действительно полезны, когда мы хотим обновить записи, но не можем использовать ORDER BY
. Они чётко определяют целевые строки:
UPDATE YourTable
SET YourColumn = 'NewValue'
WHERE ID IN (
SELECT TOP(10) ID
FROM YourTable
WHERE SomeCondition = True
ORDER BY PriorityColumn DESC
)
Таким образом, подзапросы ограничивают набор обновляемых записей с помощью условия IN
.
Визуализация
Принцип обновления записей с сортировкой ORDER BY в MS SQL можно проиллюстрировать на примере посещения вашего любимого кофейного магазина:
До обновления: [👩💼, 👨🏫, 👨🚀] <- Очередь
Порядок обновлений: [🍰->👩💼, ☕->👨🏫, 🍵->👨🚀] -- Сортировка заказов по приоритету
'UPDATE' без 'ORDER BY':
[🍰, ☕, 🍵] – Псевдослучайный порядок! О нет...
'UPDATE' с 'ORDER BY':
[☕->👨🏫, 🍵->👨🚀, 🍰->👩💼] <- ORDER BY возвращает правильный порядок заказов!
Здесь очередь играет роль базы данных, а заказы, которые мы обновляем, представляют собой UPDATE с сортировкой:
SET ROWCOUNT 1 -- Ограничение на количество обновляемых записей
UPDATE YourTable
SET YourColumn = 'YourValue'
WHERE SomeColumn = SomeValue
ORDER BY AnotherColumn
Таким образом, обновление происходит строго согласно установленной сортировке.
Примечание: MS SQL изначально не поддерживает ORDER BY
в UPDATE
. Но мы обходим это ограничение, используя SET ROWCOUNT
.
Обновление без уникального ключа
Что делать, если у вас нет уникального ключа или индекса, но требуется обновить верхние N записей? Здесь на помощь приходят подзапросы:
UPDATE YourTable
SET YourColumn = 'NewValue'
WHERE ID IN (
SELECT ID
FROM (
SELECT ID, ROW_NUMBER() OVER (ORDER BY PriorityColumn DESC) as RowNum
FROM YourTable
WHERE StatusCode = 0
) as SubQuery
WHERE RowNum <= 10
)
Вложенные подзапросы осуществляют фильтрацию записей, выбирая конкретные строки для обновления.
Полезные материалы
- UPDATE (Transact-SQL) – SQL Server | Microsoft Learn — Официальная документация Microsoft по оператору SQL UPDATE.
- sql server – Cast to date is sargable but is it a good idea? – Database Administrators Stack Exchange — Обсуждение на Stack Exchange о вопросах производительности SQL Server.
- Read Committed and Bookmark Lookup – Microsoft Community Hub — Осмотр полезных аспектов производительности в SQL Server, включая чтение и committed поиск закладок.