如何强制 SQL Server 以特定顺序执行查询
Posted
技术标签:
【中文标题】如何强制 SQL Server 以特定顺序执行查询【英文标题】:How do I force SQL Server to execute a query in a particular order 【发布时间】:2009-03-13 11:49:59 【问题描述】:我有以下问题
声明 @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 语句中完成。
【问题讨论】:
能否也请您从您的 UDF 中发布代码,我怀疑您最好重写此逻辑,也许作为子查询或 CTE。 我在这里看不到存储过程,只是一个查询和一个函数。这些是 INNER、OUTER 还是 CROSS 连接。 它们是内部联接(如果未提供联接类型,则为默认值) StingyJack 编辑删除对存储过程的引用(此代码实际上是从 SP 中提取的) 【参考方案1】:将“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'
【讨论】:
谢谢迈克。我自己也得到了同样的解决方案,但还没有写出来。出于兴趣,这将大多数查询所需的时间从 5-15 秒缩短到亚秒【参考方案2】:您可以将 udf_get_event_sitelist 的结果选择到表变量中,并且只有在 @@rowcount > 0 时才继续进行大查询
【讨论】:
【参考方案3】:您在使用内联函数时遇到的问题是它们可以为 SELECT 中返回的每一行重新计算。这意味着,如果 SELECT 语句返回 100 行,则该函数可以执行 100 次。
您应该真正遵循 Sambo99 的建议并将其提取到一个表变量(如果您认为它需要索引,则可以是一个临时表)。
【讨论】:
我假设由于我没有将 Sub 查询与外部查询相关联,因此 SQL Server 将首先评估该条件,就像许多其他数据库引擎一样)。我想我猜错了。 这两种方式都可能发生,所以盲目地说一种方式或另一种方式是假设优化器将采取的计划。我认为在任何情况下都最好是明确的。【参考方案4】:另外,修改您的 UDF 以仅返回 site_ID,因为我猜您不需要所有 (*) 列
SELECT * FROM dbo.udf_get_event_sitelist(@siteId, @userId)
到
SELECT site_id FROM dbo.udf_get_event_sitelist(@siteId, @userId)
【讨论】:
我假设 UDF 只返回一列,否则这将无效?我同意,如果指定了列,它看起来会更清晰(如果随后修改 UDF 以返回多个列,则可以防止查询被破坏)。 不仅看起来更清晰,而且会鼓励更好的实践。看到缺少指定的JOIN类型,这点肯定是要指出来的。 始终指定隐式连接类型是否被认为是一种好习惯?我知道 INNER JOIN 是默认类型,但我没有指定 JOIN 类型,因为我想要默认值。同样,我很少使用 SORT ASCENDING,因为它是隐含的。 与其把它留给下一位读者的假设(所有 f'ups 之母)不如说出来。已知默认值会更改,但可能不是这种情况。以上是关于如何强制 SQL Server 以特定顺序执行查询的主要内容,如果未能解决你的问题,请参考以下文章
如何编写oracle SQL查询以特定顺序获取匹配和不匹配的行对(基于键列)
如何查询我的所有视图设计以查找 SQL Server 中的特定字符串?