Sql 使用可选的to和from参数筛选行中的多个日期

Sql 使用可选的to和from参数筛选行中的多个日期,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一张有三个日期的桌子: id date1 date2 date3 1 1945-12-13 1930-11-04 null 2 1970-09-12 1971-09-13 1972-09-14 3 null null null 4 2000-01-01 2001-01-01 2002-01-01 我的进程传入2个参数: @date

我有一张有三个日期的桌子:

id        date1        date2        date3
1         1945-12-13   1930-11-04   null
2         1970-09-12   1971-09-13   1972-09-14
3         null         null         null
4         2000-01-01   2001-01-01   2002-01-01
我的进程传入2个参数:

@dateFrom datetime = NULL,
@dateTo datetime = NULL  
我想返回日期介于两者之间的记录。@dateFrom或@DateTo的NULL使其具有开放性

这适用于开放式情况,但不适用于两者都不为null的情况

SELECT * 
FROM Table1
WHERE (@dateFrom IS NULL 
          OR ISNULL(date1,'12/31/1753') >= @dateFrom
          OR ISNULL(date2,'12/31/1753') >= @dateFrom 
          OR ISNULL(date3,'12/31/1753') >= @dateFrom)
  AND (@dateTo IS NULL 
          OR  ISNULL(date1,'12/31/2099') <= @dateTo
          OR ISNULL(date2,'12/31/2099') <= @dateTo
          OR ISNULL(date3,'12/31/2099') <= @dateTo)
选择*
来自表1
其中(@dateFrom)为空
或者ISNULL(date1,'12/31/1753')>=@dateFrom
或者ISNULL(date2,'12/31/1753')>=@dateFrom
或ISNULL(date3,'12/31/1753')>=@dateFrom)
和(@dateTo为空)

或ISNULL(date1,'12/31/2099')您需要在范围内单独筛选每个日期字段,如下所示:

WHERE 
   (Date1 >= ISNULL(@DateFrom,'17531231')
    AND Date1 <= ISNULL(@dateTo,'20991231'))
OR
 (Date2 >= ISNULL(@DateFrom,'1753-12-31')
    AND Date2 <= ISNULL(@dateTo,'20991231'))
OR
 (Date3 >= ISNULL(@DateFrom,'1753-12-31')
    AND Date3 <= ISNULL(@dateTo,'20991231'))
在哪里
(Date1>=ISNULL(@DateFrom,'17531231')
和Date1=ISNULL(@DateFrom,'1753-12-31')
和Date2=ISNULL(@DateFrom,'1753-12-31')

和Date3您需要在范围内单独筛选每个日期字段,如下所示:

WHERE 
   (Date1 >= ISNULL(@DateFrom,'17531231')
    AND Date1 <= ISNULL(@dateTo,'20991231'))
OR
 (Date2 >= ISNULL(@DateFrom,'1753-12-31')
    AND Date2 <= ISNULL(@dateTo,'20991231'))
OR
 (Date3 >= ISNULL(@DateFrom,'1753-12-31')
    AND Date3 <= ISNULL(@dateTo,'20991231'))
在哪里
(Date1>=ISNULL(@DateFrom,'17531231')
和Date1=ISNULL(@DateFrom,'1753-12-31')
和Date2=ISNULL(@DateFrom,'1753-12-31')

和Date3只是为了用另一种方式来看待它。这个解决方案也会起作用。它使where子句变得更简单,而代价是增加一块代码和一个连接

CREATE TABLE #dates (id INT, date1 DATE, date2 DATE, date3 DATE)

INSERT INTO #dates 
VALUES
('1','12/13/1945','11/4/1930',NULL),
('2','9/12/1970','9/13/1971','9/14/1972'),
('3',NULL,NULL,NULL),
('4','1/1/2000','1/1/2001','1/1/2002')

DECLARE
    @dateFrom datetime = '1940-01-01',
    @dateTo datetime = '1950-01-01'

;WITH dateFilter AS (

SELECT id,[Date],DateIndex
FROM
(SELECT
id, date1, date2, date3
FROM #dates) p
UNPIVOT([DATE] FOR DateIndex IN ([date1],[date2],[date3])) AS up
WHERE
    up.[DATE] BETWEEN @dateFrom AND @dateTo
)

SELECT
    d.*
FROM #dates d
INNER JOIN dateFilter df
ON df.id = d.id


DROP TABLE #dates

从另一个角度来看,这个解决方案也会起作用。它使where子句更简单,但需要额外的代码块和连接

CREATE TABLE #dates (id INT, date1 DATE, date2 DATE, date3 DATE)

INSERT INTO #dates 
VALUES
('1','12/13/1945','11/4/1930',NULL),
('2','9/12/1970','9/13/1971','9/14/1972'),
('3',NULL,NULL,NULL),
('4','1/1/2000','1/1/2001','1/1/2002')

DECLARE
    @dateFrom datetime = '1940-01-01',
    @dateTo datetime = '1950-01-01'

;WITH dateFilter AS (

SELECT id,[Date],DateIndex
FROM
(SELECT
id, date1, date2, date3
FROM #dates) p
UNPIVOT([DATE] FOR DateIndex IN ([date1],[date2],[date3])) AS up
WHERE
    up.[DATE] BETWEEN @dateFrom AND @dateTo
)

SELECT
    d.*
FROM #dates d
INNER JOIN dateFilter df
ON df.id = d.id


DROP TABLE #dates

好的,这是简单的,但它会工作,我认为,因为它是在一个过程中

声明@startDate-datetimne 声明@enddate-datetime

如果@datefrom为空 设置@startDate='12/31/1753' 其他的 设置@startDate=@datefrom

如果@dateTo为空 set@endDate='12/31/2099' 其他的 设置@endDate=@dateto


使用@datefrom和@dateto来限定…

好吧,这太简单了,但我认为它会起作用,因为它在一个过程中

声明@startDate-datetimne 声明@enddate-datetime

如果@datefrom为空 设置@startDate='12/31/1753' 其他的 设置@startDate=@datefrom

如果@dateTo为空 set@endDate='12/31/2099' 其他的 设置@endDate=@dateto


使用@datefrom和@dateto来限定…

在日期更改为
'YYYYMMDD'
@Lamak fixed JUST FOR YOUThanks!之前,我拒绝对此进行更新投票,现在我可以对其进行更新投票了(我的意思是,假设列的数据类型是
DATE
而不是
DATETIME
)@JNK DUDE!你刚刚度过了我的周末。@Moose如果你的列是
DATETIME
,那么这可能会根据你的语言配置而起作用,但对某些用户可能不会。明确的做法是使用
'yyyyymmd'
而不使用
-
我拒绝对此进行更新投票,直到日期更改为
'yyyyymmdd'
>@Lamak只为YouTunks!修复了,现在我可以升级它(我的意思是,假设列的数据类型是
DATE
,而不是
DATETIME
)@JNK DUDE!你刚刚度过了我的周末。@Moose如果你的专栏是
DATETIME
,那么这可能会根据你的语言配置而起作用,但对某些用户可能不会。明确的方法是使用
'YYYYMMDD'
而不使用
-
,这是一个关于UNPIVOT的很棒的教程,谢谢!这是一个关于UNPIVOT的很棒的教程谢谢