Вы можете упростить свою проблему до «Сколько раз была сделана запись со значением 12, появившаяся до текущей записи», а затем добавьте ее к результату. Для того, чтобы получить количество записей, которое вы можете использовать OUTER APPLY
:
DECLARE @InputTable TABLE (UID INT, Std_RecordId INT);
INSERT @InputTable (UID, Std_RecordId)
VALUES (1, 10), (2, 10), (3, 12), (4, 10), (5, 10), (6, 10), (7, 12);
SELECT i.UID,
i.Std_RecordId,
t.Ind
FROM @InputTable AS i
OUTER APPLY
( SELECT Ind = COUNT(*) + 1
FROM @InputTable AS t
WHERE t.Std_RecordId = 12
AND t.UID < i.UID
) AS t;
EDIT
Просто остановиться на то, что я сказал в комментарии о временной таблице, а не табличном переменном, точном Тот же самый запрос с точно такими же данными последовательно значительно быстрее работает в моих тестах:
сценария я побежал был:
DECLARE @InputTable TABLE (UID INT, Std_RecordId INT);
INSERT @InputTable (UID, Std_RecordId)
SELECT TOP 50000
ROW_NUMBER() OVER(ORDER BY a.object_id),
CEILING(RAND(CHECKSUM(NEWID())) * 20)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b;
CREATE TABLE #InputTable (UID INT, Std_RecordId INT);
INSERT #InputTable (UID, Std_RecordId)
SELECT UID, Std_RecordId
FROM @InputTable;
SET STATISTICS TIME ON;
SELECT i.UID,
i.Std_RecordId,
t.Ind
FROM @InputTable AS i
OUTER APPLY
( SELECT Ind = COUNT(*) + 1
FROM @InputTable AS t
WHERE t.Std_RecordId = 12
AND t.UID < i.UID
) AS t;
SELECT i.UID,
i.Std_RecordId,
t.Ind
FROM #InputTable AS i
OUTER APPLY
( SELECT Ind = COUNT(*) + 1
FROM #InputTable AS t
WHERE t.Std_RecordId = 12
AND t.UID < i.UID
) AS t;
SET STATISTICS TIME OFF;
DROP TABLE #InputTable;
Поскольку я увеличил размер выборки, размер зазора увеличился, но для 10 000 строк (мне стало скучно ждать больше) переменная таблицы последовательно занимала около 7,9 секунды, тогда как временная таблица составляла в среднем 0,4. Я запустил это один раз для 50 000 строк, а переменная таблицы заняла 190 секунд, таблица temp заняла 4.6, поэтому огромная разница.
Другим преимуществом является то, что ваша временная таблица может быть проиндексирована, однако лучшая производительность, которую я нашел в таблице temp, заключалась в создании новой таблицы temp для записи позиций ваших маркеров, а затем использовать ее, чтобы дать исходную таблицу ранг:
DECLARE @InputTable TABLE (UID INT, Std_RecordId INT);
INSERT @InputTable (UID, Std_RecordId)
SELECT TOP 1000000
ROW_NUMBER() OVER(ORDER BY a.object_id),
CEILING(RAND(CHECKSUM(NEWID())) * 20)
FROM sys.all_objects a
CROSS JOIN sys.all_objects b;
DECLARE @Counter TABLE (UID INT PRIMARY KEY, Ind INT NOT NULL);
INSERT @Counter
SELECT UID, ROW_NUMBER() OVER(ORDER BY UID) + 1
FROM @InputTable
WHERE Std_RecordId = 12;
SELECT i.UID,
i.Std_RecordId,
Ind = ISNULL(t.Ind, 1)
FROM @InputTable AS i
OUTER APPLY
( SELECT TOP 1 Ind
FROM @Counter AS t
WHERE t.UID < i.UID
) AS t
ORDER BY i.UID;
для 50000 строк это последовательно побежал в менее чем за секунду, даже за миллион он работает в течение 15-20 секунд.
Я предполагаю, что могу заменить «t.Std_RecordId = 12» моим списком терминаторов, правильно? Если это так, ты качаешься, и я благодарю тебя, сэр! – Logan
Когда я получу свою процедуру, я смогу проверить ее и пометить ее правильно. :) – Logan
Я тестировал его и, похоже, работает, но он довольно медленный.Требуется 10m30s, чтобы пройти 42k записей, что совсем не так :( – Logan