Sql 如何使用包含OR子句的COALESCE生成动态
我总是使用COALESCE生成动态WHERE语句,以返回传入的值或返回所有记录 然而,当我需要检查两列时,我似乎不能这样做,如果没有传入参数,则返回所有记录。以下是我的代码片段:Sql 如何使用包含OR子句的COALESCE生成动态,sql,sql-server,sql-server-2014,Sql,Sql Server,Sql Server 2014,我总是使用COALESCE生成动态WHERE语句,以返回传入的值或返回所有记录 然而,当我需要检查两列时,我似乎不能这样做,如果没有传入参数,则返回所有记录。以下是我的代码片段: DECLARE @MaxAge INT = NULL --- Example value: 5 SELECT * FROM dbo.Vehicle WHERE DATEPART(YEAR, RegistrationDate) <= CASE WHEN @MaxAge IS NOT
DECLARE @MaxAge INT = NULL --- Example value: 5
SELECT
*
FROM
dbo.Vehicle
WHERE
DATEPART(YEAR, RegistrationDate) <=
CASE
WHEN @MaxAge IS NOT NULL
THEN (DATEPART(YEAR,GETDATE()) - @MaxAge)
ELSE DATEPART(YEAR, RegistrationDate)
END
OR
DATEPART(YEAR, ProductionDate) <=
CASE
WHEN @MaxAge IS NOT NULL
THEN (DATEPART(YEAR,GETDATE()) - @MaxAge)
ELSE DATEPART(YEAR, ProductionDate)
END
我想用通俗易懂的英语做的是:
给我车辆表中登记日期的年份部分的所有行
小于@MaxAge或ProductionDate的年份部分小于
@MaxAge。如果@MaxAge为空,则无论何时制作或注册,都将整批货交给我
有时,如果车辆尚未注册,表中的RegistrationDate值将为空。有时,如果卖方根本不知道生产日期是何时生产的,则生产日期可能为空
解决这个问题的最好办法是什么?我试着在SQL书籍和联机中查找,但找不到任何与此情况相匹配的内容。在WHERE子句中添加OR似乎返回了正确的值
DECLARE @MaxAge INT = NULL
SELECT *
FROM Vehicle
WHERE @MaxAge IS NULL OR
(DATEPART(YEAR, RegistrationDate) <=
CASE WHEN @MaxAge IS NOT NULL
THEN (DATEPART(YEAR,GETDATE()) - @MaxAge)
ELSE DATEPART(YEAR, RegistrationDate) END
OR
DATEPART(YEAR, ProductionDate) <=
CASE WHEN @MaxAge IS NOT NULL
THEN (DATEPART(YEAR,GETDATE()) - @MaxAge)
ELSE DATEPART(YEAR, ProductionDate) END
)
您可以将其简化一点:
SELECT *
FROM dbo.Vehicle
WHERE @MaxAge IS NULL -- return everything if null
OR DATEDIFF(YEAR, RegistrationDate, GETDATE()) <= @MaxAge
OR DATEDIFF(YEAR, ProductionDate, GETDATE()) <= @MaxAge
要解决此问题,您可以尝试:
SELECT *
FROM dbo.Vehicle
WHERE @MaxAge IS NULL -- return everything if null
OR DATEADD(YEAR, -@MaxAge, GETDATE()) <= RegistrationDate
OR DATEADD(YEAR, -@MaxAge, GETDATE()) <= ProductionDate
这将返回直到@MaxAge年前的今天发生的任何事情,无论时间如何
最后,在这种情况下,使用COALESCE将不起作用,因为您将只比较一列或另一列,无论哪一列先被发现为非null。因此,如果RegistrationDate不在参数范围内,而ProductionDate在参数范围内,您将错过此记录。因此,我已从答案中删除了该语句。正在使用哪个版本的SQL Server?目前有两个。那么,一个记录可能有空的registrationDate和空的ProductionDate?您的示例代码能正常工作吗?@Steven SQL Server 2014Enterprise@aron目前这是可能的。但是,如果需要,我可以更改它,并确保需要ProductionDate,您可以编写一个存储过程或简单地添加一个begin语句-语法可能不是100%正确,因为如果@maxage不为null,则通常不会编写SP,从dbo.vehicle where DATEPARTYEAR开始选择*,RegistrationDate我更喜欢第一个版本-它还允许我添加更多的列来比较,例如DeliveryDate。感谢levelonehuman给出了这个非常好的答案。@volumeone我的建议是,除非您确实需要加快阅读速度,否则应尽量提高可读性。即使有一百万行,这个特定的查询也应该非常快——你没有做任何可能会减慢速度的连接或类似操作。在我看来,当文件已经保存了几个月没有被触动时,让它对你或下一个家伙更具可读性要好得多。@ErikE的答案已经更新,包括关于合并的部分。谢谢你的接球@volumeone我已经根据ErikE的输入对我的答案做了很大的修改-请看一看,希望这有帮助!太棒了-投票通过并被选为答案。非常感谢。
SELECT *
FROM dbo.Vehicle
WHERE @MaxAge IS NULL -- return everything if null
OR DATEADD(YEAR, -@MaxAge, GETDATE()) <= RegistrationDate
OR DATEADD(YEAR, -@MaxAge, GETDATE()) <= ProductionDate
DECLARE @TodayNoTime datetime = DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0) -- 05/25/2016 00:00:00.000
SELECT *
FROM dbo.Vehicle
WHERE @MaxAge IS NULL -- return everything if null
OR DATEADD(YEAR, -@MaxAge, @TodayNoTime) <= RegistrationDate -- note the negative sign
OR DATEADD(YEAR, -@MaxAge, @TodayNoTime) <= ProductionDate