3

我有以下查询

    
声明 @userId INT  
声明 @siteId INT

设置@siteId = -1  
设置@userId = 1828  

选择 a.id 作为 alertId,  
        a.location_id,  
        a.alert_type_id,  
        a.event_id,  
        a.user_id,  
        a.site_id,  
        a.accepted_by  
FROM 警报作为    
加入 alert_types AS ats ON a.alert_type_id = ats.id
加入事件 AS tr ON a.event_id = tr.event_id
WHERE tr.end_Time 为空
AND tr.status_id = 0
和 ats.code = 'E'
AND a.site_id in (SELECT * FROM dbo.udf_get_event_sitelist(@siteId, @userId))

此查询需要 5 到 17 秒才能运行,但是在许多情况下,函数 dbo.udf_get_event_sitelist(@siteId, @userId) 不返回任何行,因此查询不会找到任何数据。

如何强制 SQL Server 首先执行用户定义的函数。我很欣赏我可以将查询重写为存储过程并首先执行子选择,但是如果可能的话,我想在单个 SQL 语句中执行此操作。

4

4 回答 4

4

使“FROM”表成为函数的结果集并将其他表连接到它

DECLARE @userId INT  
DECLARE @siteId INT

SET @siteId = -1  
SET @userId = 1828  

SELECT  a.id AS alertId,  
        a.location_id,  
        a.alert_type_id,  
        a.event_id,  
        a.user_id,  
        a.site_id,  
        a.accepted_by  
FROM    (SELECT * FROM dbo.udf_get_event_sitelist(@siteId, @userId)) dt
JOIN    alerts AS a ON dt.site_id=a.site_id
JOIN    alert_types AS ats ON a.alert_type_id = ats.id 
JOIN    events AS tr ON a.event_id = tr.event_id 
WHERE   tr.end_Time IS null
AND     tr.status_id = 0
AND     ats.code = 'E'
于 2009-03-13T13:19:57.653 回答
3

您可以将 udf_get_event_sitelist 的结果选择到表变量中,并且仅在 @@rowcount > 0 时继续进行大查询

于 2009-03-13T11:53:28.970 回答
2

使用内联函数时遇到的问题是,可以为 SELECT 中返回的每一行重新评估它们。这意味着,如果 SELECT 语句返回 100 行,则该函数可以执行 100 次。

您应该真正遵循 Sambo99 的建议并将其提取到表变量(如果您认为它需要索引,则为临时表)。

于 2009-03-13T12:00:03.867 回答
0

另外,修改你的UDF只返回site_ID,因为我猜你不需要所有(*)列

SELECT * FROM dbo.udf_get_event_sitelist(@siteId, @userId)

SELECT site_id FROM dbo.udf_get_event_sitelist(@siteId, @userId)
于 2009-03-13T11:56:33.390 回答