СТЕ выдает разный результат при запуске 2 раза подряд
В хранимой процедуре существует временная таблица #tasks
CREATE TABLE #tasks (
FkTaskType INT NOT NULL
,DateCreate DATE NOT NULL
,DateExpiration DATETIME NOT NULL
,ShopId INT NULL
,ProductId INT NULL
,Reason VARCHAR(128) NULL
,NeedRequest BIT NULL
,DocumentalRestOnCalculate NUMERIC(18, 3) NULL
,AvgSales NUMERIC(18, 3) NULL
,SaleAction BIT NULL
,MarkdownPerc INT NULL
,ManufDate DATE NULL
,CountInDelivery NUMERIC(18, 3) NULL
,CountMarkDown NUMERIC(18, 3) NULL
,Part INT NULL
)
После заполнения данными выполняется блок кода с CTE который должен удалить дубликаты:
;WITH dupl as(
SELECT
FkTaskType
,DateCreate
,DateExpiration
,ShopId
,ProductId
,Part
,NeedRequest
,DocumentalRestOnCalculate
,ManufDate
,CountInDelivery
,AvgSales
,SaleAction
,CountMarkDown
,MarkdownPerc
,Reason
,ROW_NUMBER() OVER (PARTITION BY FkTaskType, DateCreate, DateExpiration, ShopId, ProductId, NeedRequest, DocumentalRestOnCalculate, ManufDate ORDER BY ProductId) Rn
FROM #tasks)
DELETE t
FROM #tasks t
INNER JOIN dupl d ON (t.FkTaskType = d.FkTaskType AND t.DateCreate = d.DateCreate AND
t.DateExpiration = d.DateExpiration AND t.ShopId = d.ShopId AND
ISNULL(t.Reason, '') = ISNULL(d.Reason, '') AND t.Part = d.Part AND
(t.ProductId = d.ProductId)) OR (t.ProductId IS NULL)
WHERE d.Rn > 1
SELECT * FROM #tasks t
WHERE t.ProductId = 148861
RETURN 0
Если запускать ХП 2 раза подряд при одинаковых вводных, данные в #tasks
могут отличаться. Причем оба раза часть дубликатов может не удалиться и попасть в конечную выборку:
Однако если заменить CTE на времянку, такое поведение пропадает и дубликаты удаляются без проблем:
SELECT
FkTaskType
,DateCreate
,DateExpiration
,ShopId
,ProductId
,Part
,NeedRequest
,DocumentalRestOnCalculate
,ManufDate
,CountInDelivery
,AvgSales
,SaleAction
,CountMarkDown
,MarkdownPerc
,Reason
,ROW_NUMBER() OVER (PARTITION BY FkTaskType, DateCreate, DateExpiration, ShopId, ProductId, NeedRequest, DocumentalRestOnCalculate, ManufDate ORDER BY ProductId) Rn
INTO #dupl
FROM #tasks
DELETE t
FROM #tasks t
INNER JOIN #dupl d ON (t.FkTaskType = d.FkTaskType AND t.DateCreate = d.DateCreate AND
t.DateExpiration = d.DateExpiration AND t.ShopId = d.ShopId AND
ISNULL(t.Reason, '') = ISNULL(d.Reason, '') AND t.Part = d.Part AND
(t.ProductId = d.ProductId)) OR (t.ProductId IS NULL)
WHERE d.Rn > 1
SELECT * FROM #tasks t
WHERE t.ProductId = 148861
TRUNCATE TABLE #f
RETURN 0
ROW_NUMBER()
и для CTE dupl
и для времянки #dupl
всегда выдает корректный результат.
Чем обусловлено такое поведение CTE?
База данных на SQL Server 2019.
Источник: Stack Overflow на русском