Sql server 执行SQL Server案例where子句的最佳方法
我正在尝试构建一个SQL SP来查询报表。它有几个参数可以为NULL或应该有一个值。我正在使用下面的代码。有没有其他方法可以做到这一点,更干净或更恰当。我假设如果一个参数为Null,我将只执行1=1的过滤条件Sql server 执行SQL Server案例where子句的最佳方法,sql-server,Sql Server,我正在尝试构建一个SQL SP来查询报表。它有几个参数可以为NULL或应该有一个值。我正在使用下面的代码。有没有其他方法可以做到这一点,更干净或更恰当。我假设如果一个参数为Null,我将只执行1=1的过滤条件 DECLARE @Arg1 VARCHAR(10) = NULL, @Arg2 VARCHAR(10) = NULL SELECT * FROM Table1 WHERE (CASE WHEN (@Arg1 IS NULL) THEN 1 EL
DECLARE @Arg1 VARCHAR(10) = NULL,
@Arg2 VARCHAR(10) = NULL
SELECT * FROM Table1
WHERE
(CASE WHEN (@Arg1 IS NULL) THEN
1
ELSE
@Arg1
END) =
(CASE WHEN (@Arg1 IS NULL) THEN
1
ELSE
Location
END)
AND
(CASE WHEN (@Arg2 IS NULL) THEN
1
ELSE
@Arg2
END) =
(CASE WHEN (@Arg2 IS NULL) THEN
1
ELSE
Sex
END)
你就不能这样做吗
where
(@Arg1 is null or @Arg1 = Location)
and
(@Arg2 is null or @Arg2 = Sex)
然后,如果
@Arg1
(或2)为空,则谓词的该部分为TRUE
和且与下一个谓词一起使用。您不能这样做吗
where
(@Arg1 is null or @Arg1 = Location)
and
(@Arg2 is null or @Arg2 = Sex)
然后,如果@Arg1
(或2)为空,则谓词的该部分为TRUE
,并且和
'd与下一个谓词一起使用。另一种可能,甚至更短,是使用:
也就是说,当@arg1和@arg2有值时,使用它们,否则,使用有问题的列;由于Location=Location
始终为真(至少在不为空时,您自己的代码中存在相同的问题)。另一种可能,甚至更短,是使用:
也就是说,当@arg1和@arg2有值时,使用它们,否则,使用有问题的列;由于Location=Location
始终为真(至少当不为空时,您自己的代码中存在相同的问题)。另一种可能性是
where IsNull(@Arg1,Location) = Location
and IsNull(@Arg2, Sex) = Sex
这几乎就是@IFLoop的答案,但是IsNull
比COALESCE
稍微快一点
运行以下查询(在我的计算机中):
成本:27%
select *
from sys.tables
where Coalesce(@Arg1,name) = name
成本27%
select *
from sys.tables
where (@Arg1 is null or @Arg1 = name)
成本45%
请运行并查看执行计划
但是,如果表的行数增加,差异就会消失,因为这主要取决于表扫描时间:
select *
from sys.all_Columns
where IsNull(@Arg1, name) = name
成本:33%
select *
from sys.all_Columns
where Coalesce(@Arg1,name) = name
成本34%
select *
from sys.all_Columns
where (@Arg1 is null or @Arg1 = name)
成本33%另一种可能性是
where IsNull(@Arg1,Location) = Location
and IsNull(@Arg2, Sex) = Sex
这几乎就是@IFLoop的答案,但是IsNull
比COALESCE
稍微快一点
运行以下查询(在我的计算机中):
成本:27%
select *
from sys.tables
where Coalesce(@Arg1,name) = name
成本27%
select *
from sys.tables
where (@Arg1 is null or @Arg1 = name)
成本45%
请运行并查看执行计划
但是,如果表的行数增加,差异就会消失,因为这主要取决于表扫描时间:
select *
from sys.all_Columns
where IsNull(@Arg1, name) = name
成本:33%
select *
from sys.all_Columns
where Coalesce(@Arg1,name) = name
成本34%
select *
from sys.all_Columns
where (@Arg1 is null or @Arg1 = name)
成本33%好了,我在其他SP上看到了这段代码,这段代码看起来更好。这是我的案例中最好的吗?我对你的案例不太了解,但这更容易阅读,也更常用。我每次遇到这个问题都会使用这种方法,而且我从来都不需要其他方法。谢谢,我们继续这样做,只是继续使用我在其他SP上看到的代码,这一个似乎更好。这是我的案例中最好的吗?我对你的案例不太了解,但这更容易阅读,也更常用。每当我遇到这个问题时,我都会使用这种方法,而且我从来都不需要其他方法。谢谢,继续看这篇文章。您所做的是一种全面的查询。如果处理不当,可能会出现一些严重的性能问题。嗨@SeanLange,我没有完全正确地阅读这篇文章,关于如何正确处理这篇文章的任何提示。看看这篇文章。您所做的是一种全面的查询。如果处理不当,可能会出现一些严重的性能问题。您好@SeanLange,我没有完全正确地阅读这篇文章,有没有关于如何正确处理这一问题的提示。这是我的计划,但Location=Location不是性能问题的一个因素?@Sid我刚刚做了一个测试,看起来Location=Location
的评估方式与您所想的不同。事实上它非常快。SQL Server可以导出列对自身的引用,并且几乎立即返回true
表达式。字符串比较只有在表达式中有基于字符类型的参数时才会发生。@KingKing我们应该说Location=Location实际上更快/与NULL相同的比较是NULL吗?@Sid我认为它们几乎是一样的。如果右侧的列可以为NULL,则会有严重的差异,因为NULL=NULL
不匹配;在这种情况下,类似于COALESCE(@arg1,location,1)=COALESCE(location,1)
的方法可能会更好,但在这种情况下,这里的可读性并没有太大改进,所以我选择Dave的解决方案。当它不可为空时,计划员(原则上,无论如何)可以完全避免检查列。这是我的计划,但Location=Location不是性能问题的一个因素?@Sid我刚刚做了一个测试,看起来Location=Location
的计算方式与您所想的不同。事实上它非常快。SQL Server可以导出列对自身的引用,并且几乎立即返回true
表达式。字符串比较只有在表达式中有基于字符类型的参数时才会发生。@KingKing我们应该说Location=Location实际上更快/与NULL相同的比较是NULL吗?@Sid我认为它们几乎是一样的。如果右侧的列可以为NULL,则会有严重的差异,因为NULL=NULL
不匹配;在这种情况下,类似于COALESCE(@arg1,location,1)=COALESCE(location,1)
的方法可能会更好,但在这种情况下,这里的可读性并没有太大改进,所以我选择Dave的解决方案。当它不可为null时,规划人员可以(原则上,无论如何)完全避免检查列。因此,我可以问一下IsNull/Coalesce vs(@Arg1为null或@Arg1=Location)之间的性能问题吗?我认为性能差异非常小,表需要很小才能感知到一些差异,否则,与表扫描相比,在这些函数中花费的时间将是荒谬的。因此,我可以问一下IsNull/Coalesce与(@Arg1为null或@Arg1=Location)之间的性能问题吗?我认为性能差异太小,表