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的很棒的教程谢谢