Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何使用包含OR子句的COALESCE生成动态_Sql_Sql Server_Sql Server 2014 - Fatal编程技术网

Sql 如何使用包含OR子句的COALESCE生成动态

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

我总是使用COALESCE生成动态WHERE语句,以返回传入的值或返回所有记录

然而,当我需要检查两列时,我似乎不能这样做,如果没有传入参数,则返回所有记录。以下是我的代码片段:

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