//这段代码会报错
where
case when (@a = null)
then 1 = 1
else @a=a
and b=@b
//这样写是正确的
where
(1 = (CASE WHEN @a IS NULL THEN 1 ELSE 0 END)
OR a=@a )
AND b=@b
附上原文如下:sqlserver中where条件加判断
我看到很多方法都是在折腾CASE WHEN THEN
但实际上如果相对复杂一点,这样写会造成
其实可以优化为:
//优化前:
select * from table
where
(1 = (CASE WHEN @a IS NULL THEN 1 ELSE 0 END)
OR a=@a )
AND b=@b
//优化后:
DECLARE @a varchar(50)
select * from table
where a=ISNULL(@a,1)
如果只是在where子句后加是否为null的判断的话 完全可以使用ISNULL()函数来处理。
略复杂一点可以这样:
exp:
//业务场景:查询整年销售的一个累计金额,若传过来的查询时间为空的话,则默认查询从该年一月份到十二月份的销售总金额。
//若查询时间不为空的话,则查询传过来的开始时间和结束时间之间的销售总金额。
DECLARE @startTime datetime=null --搜索的开始时间
DECLARE @endTime datetime=null --搜索的结束时间
--本年最后一天
DECLARE @LastDayOfTheYear DATETIME=DATEADD(year, datediff(year, 0, dateadd(year, 1, getdate())), -1)
DECLARE @TheLastDay DATETIME=dateadd(year, datediff(year, 0, dateadd(year, 1, @endTime)), -1)
--本年第一天
DECLARE @FirstDayOfTheYear DATETIME=DATEADD(year, datediff(year, 0, getdate()), 0)
DECLARE @FirstDay DATETIME=dateadd(year, datediff(year, 0, @startTime), 0)
--本年累计金额 临时表
SELECT op.OrderID,SUM((op.Quantity-ISNULL(op.ReturnNum ,0))*op.UnitPrice) AS yearmoney INTO #CumulativeAmount
FROM OrderProduct op
LEFT JOIN Orders o ON op.OrderID=o.OrderID
WHERE o.FinishTimeISNULL(@FirstDay,@FirstDayOfTheYear)
GROUP BY op.OrderID
如果是在where子句后根据查询结果进行判断来附加查询条件则可以这样
exp:
--积分表 表结构如下:
CREATE TABLE [dbo].[Score_Table](
[ID] [int] IDENTITY(1,1) NOT NULL, --主键自增
[PreScore] [int] NOT NULL, --修改前积分
[Score] [int] NOT NULL, --本次修改积分
[TotalScore] [int] NOT NULL, --修改后总积分
[Flag] [int] NOT NULL --标识 -1扣减,1增加
) ON [PRIMARY]
GO
--查询积分异常
--flag=1 s.TotalScore<>(s.Score+s.PreScore)
--flag=-1 s.TotalScore<>(s.PreScore-s.Score)
--根据Flag来进行判断 若为增加积分的话 那么 s.TotalScore<>(s.Score+s.PreScore) 为异常
--若为减少积分的话 那么 s.TotalScore<>(s.PreScore-s.Score) 为异常
select *,Row_number() over(order by s.ID desc) as rowno
from Score_Table s where ((s.Flag=1 and s.TotalScore<>(s.PreScore+s.Score)) OR (s.Flag=-1 and s.TotalScore<>(s.PreScore-s.Score)))