SQL Server使用Case或其他方法删除多个if语句

时间:2013-10-26 15:24:57

标签: sql-server tsql

这些是我传递给存储过程的一些位值,并根据这些值生成了where子句

@booking bit,
@drs bit,
@manifest bit,
@receiving bit,
@status bit

非常简单

if (@booking=0)
Select * from Table where ColumnName='Booking'
if (@drs=1)
Select * from Table where ColumnName=DRS'
--so on based on other bit values

查询保持不变但基于位值我得到结果集并合并结果集。

在简单的一天,这个查询看起来像这个

Select * from Table where ColumnName in ('Booking','DRS')

我不想在我的存储过程中使用多个if语句,并且无论如何都要在单个查询中进行。

2 个答案:

答案 0 :(得分:2)

您只需要在选项和OR选项之间使用AND语句,并使用启用它的位。

Select * from Table
where (   (ColumnName='DRS' AND @drs = 1)
       OR (ColumnName='Booking' AND @booking = 1)
       OR (ColumnName='Manifest' AND @manifest = 1) 
       OR (ColumnName='Receiving' AND @receiving = 1) 
       OR (ColumnName='Status' AND @status = 1)
      )

正如Aaron在评论中指出的那样,这可能会影响您的表现,具体取决于查询计划的生成方式。

答案 1 :(得分:2)

另一个选项是动态SQL。它可以防止我提到的反对斯科特答案的问题:

  

请谨慎使用,因为您只会获得此模式的单个查询计划,并且根据ColumnName中值的偏差,它可能不是该作业的最佳查询计划。例如,如果表中出现“DRS”一次,并且表中出现“预订”600,000次,那么两个非常不同的计划可能对这些结果中的每一个都最有效......但是您将获得两个计划的计划将取决于首先生成的计划。

使用动态SQL,您可以使用optimize for ad hoc workloads服务器设置(假设SQL Server 2008+)来防止缓存膨胀,您仍然可以使用OPTION (RECOMPILE)击败参数嗅探。这是一个简单的例子:

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'SELECT columns -- never use * in production
  FROM dbo.Table -- always use schema prefix
  WHERE ColumnName = @param OPTION (RECOMPILE);';

DECLARE @param VARCHAR(32);

SET @param = CASE WHEN @drs       = 1 THEN 'DRS'
                  WHEN @booking   = 1 THEN 'Booking'
                  WHEN @manifest  = 1 THEN 'Manifest'
                  WHEN @receiving = 1 THEN 'Receiving'
                  WHEN @status    = 1 THEN 'Status' 
END;

EXEC sp_executesql @sql, N'@param VARCHAR(32)', @param;

维护起来更加丑陋,但是它更难以帮助你制定一个糟糕的计划(以及结果导致的糟糕表现)。