У меня есть код с оператором MERGE
, вызывающим скалярную функцию, и у меня очень низкая производительность.
Этот код может занять у меня 30 минут и более, а иногда он может потерпеть неудачу в середине.
Мой код:
MERGE INTO Table1 AS md
USING (SELECT * FROM Table2 edb
WHERE edb.FileId = @FileId
AND edb.IsRowError = 0) edbTable ON dbo.GetId(edbTable.Filed1, edbTable.Filed2, edbTable.Filed3, edbTable.Filed4, edbTable.Filed5, edbTable.Filed6) = md.Id
AND md.IsActive = 1
WHEN MATCHED THEN
UPDATE
SET .
.
.
Функция:
ALTER FUNCTION [dbo].[GetId]
(@Filed1 NVARCHAR(9),
@Filed2 NVARCHAR(9),
@Filed3 NVARCHAR(13),
@Filed4 INT,
@Filed5 DATE,
@Filed6 INT)
RETURNS INT
AS
BEGIN
DECLARE @Id INT = NULL
IF ((@Filed5 IS NULL) OR (@Filed6 = 0))
BEGIN
SET @Id = (SELECT TOP 1 md.Id
FROM Table1 md with(NOLOCK)
JOIN Table3 mb with(NOLOCK) ON md.Table3Id = mb.Id
WHERE (mb.Filed1 = @Filed1 AND mb.Filed2 = @Filed2
OR mb.Filed1 = @Filed2 AND mb.Filed2 = @Filed1)
AND mb.Filed7 = 1
AND @Filed3 = md.Filed3
AND @Filed4 = md.Filed4
ORDER BY md.LastUpdateDate DESC)
IF @Id IS NOT NULL
RETURN @Id
ELSE
SET @Id = (SELECT TOP 1 md.Id
FROM Table1 md with(NOLOCK)
JOIN Table3 mb with(NOLOCK) ON md.Table3Id = mb.Id
WHERE (mb.Filed1 = @Filed1 OR mb.Filed1 = @Filed1)
AND mb.Filed7 = 1
AND @Filed3 = md.Filed3
AND Filed4 = md.Filed4
AND @Filed1 > 0
ORDER BY md.LastUpdateDate DESC)
IF @Id IS NOT NULL
RETURN @Id
ELSE
set @Id =(select top 1 md.Id from Table1 md with(NOLOCK)
join Table3 mb with(NOLOCK) on md.Table3Id = mb.Id
where (mb.Filed1 = @Filed2
or mb.Filed2 = @Filed2 )
and mb.Filed7 = 1
and @Filed3 = md.Filed3
and @Filed4 = md.Filed4
and @Filed2 >0
order by md.LastUpdateDate desc)
end
else
begin
set @Id = (select top 1 md.Id from Table1 md with(NOLOCK)
join Table3 mb with(NOLOCK) on md.Table3Id = mb.Id
where (mb.Filed1 = @Filed1 and mb.Filed2 = @Filed2
or mb.Filed1 = @Filed2 and mb.Filed2 = @Filed1 )
and mb.Filed7 = 1
and @Filed3 = md.Filed3
and @Filed4 = md.Filed4
and (@Filed5 = md.ContractDate or (@Filed5 is null and md.ContractDate is null))
and @Filed6 = md.PurchasePrice)
if @Id is not NULL
RETURN @Id
else
set @Id =(select top 1 md.Id from Table1 md with(NOLOCK)
join Table3 mb with(NOLOCK) on md.Table3Id = mb.Id
where (mb.Filed1 = @Filed1
or mb.Filed2 = @Filed1 )
and mb.Filed7 = 1
and @Filed3 = md.Filed3
and @Filed4 = md.Filed4
and (@Filed5 = md.ContractDate or (@Filed5 is null and md.ContractDate is null))
and @Filed6 = md.PurchasePrice
and @Filed1 >0)
if @Id is not NULL
RETURN @Id
else
set @Id =(select top 1 md.Id from Table1 md with(NOLOCK)
join Table3 mb with(NOLOCK) on md.Table3Id = mb.Id
where (mb.Filed1 = @Filed2
or mb.Filed2 = @Filed2 )
and mb.Filed7 = 1
and @Filed3 = md.Filed3
and @Filed4 = md.Filed4
and (@Filed5 = md.ContractDate or (@Filed5 is null and md.ContractDate is null))
and @Filed6 = md.PurchasePrice
and @Filed2 >0)
if @Id is not NULL
RETURN @Id
end
RETURN @Id
END
Что мне нужно изменить?
Как я могу изменить код?
Мне нужна вся статистика If
, потому что есть предпочтение, какую запись извлечь, я не могу преобразовать ее в join
.
Потому что, если кто-то join
, они дадут мне положительный ответ, так что он даст мне список всех, кто вышел из группы населения, и важно знать, из-за первого, второго или третьего присоединения, потому что я есть приоритеты на выбор.
Если я сделаю это вместо if
до join
, есть ли способ вытащить первую строку, которая выходит? То есть, если я присоединяюсь, и у первого нет результатов, а у второго, а в третьем, будет возвращен только результат второго, а не третьего - есть ли такая вещь?