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

时间:2014-08-29 16:40:14

标签: 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

我的proc传递了2个参数:

@dateFrom datetime = NULL,
@dateTo datetime = NULL  

我想返回两者之间有任何日期的记录。 @dateFrom或@DateTo的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)

如果我通过@dateFrom =&#39; 1940-01-01&#39;和@dateTo =&#39; 1950-01-01&#39;, 我只想要第一张唱片,但我得到了1,2和4,因为它们都有日期&gt; 1940。

我无法绕过如何构建它。

已更改列名和表名以保护无辜者。

3 个答案:

答案 0 :(得分:3)

您需要在范围内单独过滤每个日期字段,如下所示:

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'))

否则,您不会检查每个日期字段的范围,只是该行中的日期符合其中一个条件。

答案 1 :(得分:1)

只是为了另一种方式来看待它。这个解决方案也可行。它使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

答案 2 :(得分:0)

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

声明@startDate datetimne 声明@enddate datetime

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

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

并使用@datefrom和@dateto来限定......