我有一张类似
的表格Event ID Date Instructor
1 1/1/2000 Person 1
1 1/1/2000 Person 2
现在我要做的是返回这些数据,以便每个事件都在一行上,而教师都在一个列中,并使用<br>
标记'Person 1 <br> Person 2'
目前我这样做的方法是使用函数
CREATE FUNCTION fnReturnInstructorNamesAsHTML
(
@EventID INT
)
RETURNS VARCHAR(max)
BEGIN
DECLARE @Result VARCHAR(MAX)
SELECT
@result = coalesce(@result + '<br>', '') + inst.InstructorName
FROM
[OpsInstructorEventsView] inst
WHERE
inst.EventID = @EventID
RETURN @result
END
然后我的主存储过程将其称为
SELECT
ev.[BGcolour],
ev.[Event] AS name,
ev.[eventid] AS ID,
ev.[eventstart],
ev.[CourseType],
ev.[Type],
ev.[OtherType],
ev.[OtherTypeDesc],
ev.[eventend],
ev.[CourseNo],
ev.[Confirmed],
ev.[Cancelled],
ev.[DeviceID] AS resource_id,
ev.Crew,
ev.CompanyName ,
ev.Notes,
dbo.fnReturnInstructorNamesAsHTML(ev.EventID) as Names
FROM
[OpsSimEventsView] ev
JOIN
[OpsInstructorEventsView] inst
ON
ev.EventID = inst.EventID
这非常慢,我看着每次调用DB的时间是4秒。有没有办法让我提高功能的性能?它是一个相当小的功能,所以我不知道我能在这里做什么,而且我无法看到将COALESCE用于主程序的SELECT的方法。
非常感谢任何帮助,谢谢。
答案 0 :(得分:1)
你可以尝试这样的事情。
SELECT
ev.[BGcolour],
ev.[Event] AS name,
ev.[eventid] AS ID,
ev.[eventstart],
ev.[CourseType],
ev.[Type],
ev.[OtherType],
ev.[OtherTypeDesc],
ev.[eventend],
ev.[CourseNo],
ev.[Confirmed],
ev.[Cancelled],
ev.[DeviceID] AS resource_id,
ev.Crew,
ev.CompanyName ,
ev.Notes,
STUFF((SELECT '<br>'+inst.InstructorName
FROM [OpsInstructorEventsView] inst
WHERE ev.EventID = inst.EventID
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 4, '') as Names
FROM
[OpsSimEventsView] ev
不确定您在主查询中加入OpsInstructorEventsView
的原因。我在这里删除它,但如果你需要,你可以再添加它。
答案 1 :(得分:0)
要注意的一些事项:
1)函数的开销使得调用成本很高,尤其是在可能返回数千行的查询的select语句中。它必须为它们中的每一个执行该功能。考虑将函数的行为合并到主存储过程中,SQL Server可以更好地利用其优化器。
2)由于您要在两个表中加入事件ID,请确保在这两个列上有索引。我希望你这样做,因为那些似乎都是主键列,但请确保。索引可以产生巨大的差异。
3)将您的coalesce调用转换为等效的case语句,以消除调用该函数的开销。
答案 2 :(得分:0)
是的,使其成为INLINE Table-Value SQL函数:
CREATE FUNCTION fnReturnInstructorNamesAsHTML
( @EventID INT )
RETURNS Table
As
Return
SELECT InstructorName + '<br>' result
FROM OpsInstructorEventsView
WHERE EventID = @EventID
Go
然后,在您的SQL语句中,像这样使用它
SELECT ]Other stuff],
(Select result from dbo.fnReturnInstructorNamesAsHTML(ev.EventID)) as Names
FROM OpsSimEventsView ev
JOIN OpsInstructorEventsView inst
ON ev.EventID = inst.EventID
我不清楚你在问题中显示的查询如何连接结果的一行中的多行数据,但问题是普通的UDF在使用时编译,在每次使用时都是如此,因此对于每一行在您的输出结果中,Query processopr必须再次重新编译UDF。对于“内联表值”UDF,这不是True,因为它在传递给SQL优化器(生成语句缓存计划的子系统)之前将sql折叠到外部sql中,因此UDF只编译一次。