Sql 条件WHERE子句

Sql 条件WHERE子句,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我需要SQL Server中的条件WHERE子句的解决方案。我不知道如何根据声明的变量将函数添加到WHERE子句中。我将用所需的逻辑将条件部分括起来 DECLARE @distance bigint DECLARE @photosneeded bigint SET @distance * 50 SELECT * FROM users u WHERE [IF @distance > 0 THEN distance_function(lat1,lon1,lat2,lon2)<=@

我需要SQL Server中的条件WHERE子句的解决方案。我不知道如何根据声明的变量将函数添加到WHERE子句中。我将用所需的逻辑将条件部分括起来

DECLARE @distance bigint
DECLARE @photosneeded bigint

SET @distance * 50

SELECT * FROM users u
WHERE
  [IF @distance > 0 THEN distance_function(lat1,lon1,lat2,lon2)<=@distance END]
  AND
  [IF @photosneeded>0 THEN u.photo IS NOT NULL AND u.photo <>'' END]

可以使用简单的WHERE子句执行此操作:

SELECT * FROM users u
WHERE
(@distance <= 0 or (distance_function(lat1,lon1,lat2,lon2)<=@distance))
AND
(@photosneeded <= 0 or (u.photo IS NOT NULL AND u.photo <>''))

但是,您需要在子句中小心处理这种情况,因为它确实会破坏执行计划优化。有关原因的更多信息,请参见@Iain的答案。

我的建议是将其分成三个独立的过程——一个用于使用第一个子句的完整查询,另一个用于使用第二个子句的完整查询,第三个作为主查询,根据条件调用其中一个。在过去,SQL Server只编译条件子句的第一个使用的分支时会出现问题我不确定2008年是否是这样,因此使用单独的存储过程可以避免这种情况,而且这是一种简单的组织方式。

我很确定这在2008年仍然是一个问题——因此我在回答的底部给出了警告。不过,我认为你的回答更清楚地解释了根本原因。这是一条路,我在《MCTS自学成绩单考试70-433:Microsoft®SQL Server 2008数据库开发》一书中找到了同样的建议,因此它仍然适用于SQL Server 2008。执行计划的使用得到了优化,因为几个简单的可重用执行计划可以轻松地组合到属于主存储过程的执行计划中。谢谢@ChrisShain,我想你比我快了16秒有趣的是看看如何使用标准where子句。我现在使用的是SQL 2012,这是否也适用于2012?不知道SQL Server 2012。在上面提到的书的第163-164页中,它指出,如果过程中存在分支,并且属于每个分支的代码块都非常不同,那么每个代码块都应该成为一个过程。在masterproc中,根据分支条件调用这些过程;创建PROC Proc1 BEGIN IF THEN ELSE END-可替换为创建PROC Proc1 BEGIN IF THEN EXEC PROC_BLOCK A ELSE EXEC PROC_BLOCK B END您可以尝试这两种解决方案,并查看性能指标是否存在差异。在这种情况下,我是否同意SQL上的执行计划?您的里程可能会有所不同。我在SQL Server 2012的新增文档中没有看到任何相关内容,但这并不意味着它没有改变。您应该知道,虽然它在逻辑上可以工作,但性能可能不是很好,Iain的解决方案几乎肯定会表现得更好。
SELECT * FROM users u
WHERE
 ( @distance <= 0 or distance_function(lat1,lon1,lat2,lon2)<=@distance )
 and
 ( @photosneeded <= 0 or isnull(u.photo, '') <> '' )