[英]SQL Table Valued Function in Select Statement
SQL不是我最好的事情,但我一直在嘗試優化這個存儲過程。 它有多個標量值函數,我試圖改變為表值函數,因為我在很多地方讀到它是一種更有效的方法。 現在我已經制作了但不是真正確定如何實現,或者我可能只是沒有正確創建它們。
這是我正在打電話的功能。
Alter FUNCTION [IsNotSenateActivityTableValue]
(
@ActivityCode int,
@BillId int,
@TextToDisplay varchar(max)
)
returns @T table(result varchar(max))
as
begin
DECLARE @result varchar(max);
declare @countcodes int;
declare @ishousebill int;
select @ishousebill = count(billid)
from BillMaster
where BillID = @BillID and Chamber = 'H'
If (@ishousebill = 0)
begin
SELECT @countcodes = count([ActivityCode])
FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%' and ActivityType = 'S'
and [ActivityCode] = @ActivityCode
if (@countcodes = 0)
begin
set @result = 'test'
end
else
begin
set @result = 'test2'
end
end
else
begin
set @result = @TextToDisplay
end
RETURN
END
這就是我試圖像這樣打電話給他們的方式。 我希望能夠把它們放在頂部,但實際上任何有用的東西都會很好。
SELECT distinct
ActionDates.result as ActionDate
,ActivityDescriptions.result as ActivityDescription
FROM BillWebReporting.vwBillDetailWithSubjectIndex as vw
left outer join [BillWebReporting].[HasHouseSummary] as HasSummary on vw.BillID = HasSummary.BillID
outer APPLY dbo.IsNotSenateActivityDateTableValue(ActivityCode,vw.BillID,[ActionDate]) ActionDates
OUTER APPLY dbo.IsNotSenateActivityTableValue(ActivityCode,vw.BillID,[ActivityDescription]) as ActivityDescriptions
獲取計數只是為了查看是否存在至少一行是非常昂貴的。 您應該使用EXISTS
,它可能會短路而不會實現整個計數。
這是一種使用內聯表值函數而不是多語句表值函數的更有效方法。
ALTER FUNCTION dbo.[IsNotSenateActivityTableValue] -- always use schema prefix!
(
@ActivityCode int,
@BillId int,
@TextToDisplay varchar(max)
)
RETURNS TABLE
AS
RETURN (SELECT result = CASE WHEN EXISTS
(SELECT 1 FROM dbo.BillMaster
WHERE BillID = @BillID AND Chamber = 'H'
) THEN @TextToDisplay ELSE CASE WHEN EXISTS
(SELECT 1 FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%'
and ActivityType = 'S'
and [ActivityCode] = @ActivityCode
) THEN 'test2' ELSE 'test' END
END);
GO
當然它也可能只是一個標量UDF ......
ALTER FUNCTION dbo.[IsNotSenateActivityScalar] -- always use schema prefix!
(
@ActivityCode int,
@BillId int,
@TextToDisplay varchar(max)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @result VARCHAR(MAX);
SELECT @result = CASE WHEN EXISTS
(SELECT 1 FROM dbo.BillMaster
WHERE BillID = @BillID AND Chamber = 'H'
) THEN @TextToDisplay ELSE CASE WHEN EXISTS
(SELECT 1 FROM [HouseCoreData].[dbo].[ActivityCode]
where ActivityDescription not like '%(H)%'
and ActivityType = 'S'
and [ActivityCode] = @ActivityCode
) THEN 'test2' ELSE 'test' END
END;
RETURN (@result);
END
GO
表值函數返回一個表,其中,與任何其他表一樣,必須插入行。
而不是set @result = .....
,做:
INSERT INTO @T (result) VALUES ( ..... )
編輯 :作為旁注,我真的不明白這個函數是表值的原因。 你實際上是返回一個值。
首先,UDF通常非常不具備性能。 我不確定MySQL,但在Sql Server中,每次重新編譯UDF(FOR EACH ROW OF OUTPUT)都會執行它,除了所謂的內聯 UDF,它只有一個select語句,它被折疊到SQL中它包含在外部查詢中...因此只編譯一次。
MySQL確實有內聯表值函數 ,而不是在SQL Server中使用它,語法如下:
CREATE FUNCTION IsNotSenateActivityTableValue
(
@ActivityCode int,
@BillId int,
@TextToDisplay varchar(max)
)
RETURNS TABLE
AS
RETURN
(
Select case
When y.bilCnt + z.actCnt = 0 Then 'test'
when y.bilCnt = 0 then 'test2'
else @TextToDisplay end result
From (Select Count(billId) bilCnt
From BillMaster
Where BillID = @BillID
And Chamber = 'H') y
Full Join
(Select count([ActivityCode]) actCnt
From [HouseCoreData].[dbo].[ActivityCode]
Where ActivityDescription not like '%(H)%'
And ActivityType = 'S'
And [ActivityCode] = @ActivityCode) z
)
GO
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.