如何在T-sql中实现相当于“短路求值”
Posted
技术标签:
【中文标题】如何在T-sql中实现相当于“短路求值”【英文标题】:How to achieve the equivalent of "short-circuit evaluation" in T-sql 【发布时间】:2017-05-21 07:25:36 【问题描述】:我有这个选择场景:
我想先返回完全匹配,然后只使用简单的 T-sql 查询逐步检查部分匹配。
select * from accounts where
mobile = @mobile or
mobile like @mobile +'%' or
mobile like '%'+@mobile or
mobile like '%'+@mobile +'%'
我了解T-sql
执行一次性操作。
如何才能做到最好?
【问题讨论】:
SQL Server 不支持“短路”布尔评估,也没有“打开”选项...... @marc_s 这就是我问的原因,我们如何实现短路 where 子句的 等效 【参考方案1】:您可以这样做的一种方法是将查询拆分为多个查询。我并不是说这会带来最好的性能,但是:
select * from accounts
where mobile = @mobile
union
select * from accounts
where like @mobile +'%'
and not exists (select 1 from accounts where mobile = @mobile)
union
select * from accounts
where mobile like '%'+@mobile
and not exists (select 1 from accounts where like @mobile +'%')
union
select * from accounts
where mobile like '%'+@mobile +'%'
and not exists (select 1 from accounts where like '%'+@mobile)
您可以做的其他更“程序化”的事情是使用@@ROWCOUNT
,因为它模拟短路,所以应该会提供更好的性能。
select * from accounts
where mobile = @mobile
if @@rowcount = 0
select * from accounts
where like @mobile +'%'
if @@rowcount = 0
select * from accounts
where mobile like '%'+@mobile
if @@rowcount = 0
select * from accounts
where mobile like '%'+@mobile +'%'
【讨论】:
这是因为“All-At-Once Operations”? @CharlesOkwuagwu 好吧,你首先需要了解 SQL 是一种声明性语言,你不告诉它如何做事,你只告诉它你想要的结果,它会得到它你。让我看看能不能找到一篇更详细地解释这一点的博文。我所做的有点像“短路”,实际上我将其分解为单独的查询。第一个将自行运行,然后是第二个,然后是第三个和第四个,但从第二个查询开始,如果前一个查询返回任何结果,它们还有一个附加条件。 @@rowcount 的变化非常棒。谢谢【参考方案2】:您可以在 CASE 中进行评估并提供排名值:
select
mobile,
case
when mobile = @mobile then 1
when mobile like @mobile +'%' then 2
when mobile like '%'+@mobile then 3
when mobile like '%'+@mobile +'%' then 4
end as [Rank]
from accounts where
mobile = @mobile or
mobile like @mobile +'%' or
mobile like '%'+@mobile or
mobile like '%'+@mobile +'%'
order by [Rank]
【讨论】:
此解决方案不会像 union 解决方案那样产生重复。谢谢 它也不会多次遍历源表。添加一个外部过滤器查询,我认为它的作用相同。 我明白你在做什么,我同意它是正确的,并且从基于集合的角度来看是首选解决方案,但它并不是真正的短路,因为它很可能会覆盖整个表,至少一次。 是的,在这种情况下,由于使用了通配符模式,即使列被索引,两个 WHERE 子句也需要全表扫描,通过限制查询来避免这种情况应该是绝对优先级.以上是关于如何在T-sql中实现相当于“短路求值”的主要内容,如果未能解决你的问题,请参考以下文章