我有一张有三个日期的表格:
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。
我无法绕过如何构建它。
已更改列名和表名以保护无辜者。
答案 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来限定......