如何在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中实现相当于“短路求值”的主要内容,如果未能解决你的问题,请参考以下文章

到T-SQL DML 三级的阶梯:在SQL server中实现关系模型

在SQL Server中实现关系模型

如何在这个特定的 T-SQL 查询中使用表变量?

Javascript短路表达式

如何在c#中实现决策矩阵

在 Keras 中实现模型。如何解释填充/步幅值?