我在SQL Server中有一个表,其中包含各种日期范围。
表格的开始日期和结束日期如下: -
start_date end_date
======================= =======================
2011-02-21 00:00:00.000 2011-02-25 00:00:00.000
2011-04-18 00:00:00.000 2011-04-29 00:00:00.000
2011-05-31 00:00:00.000 2011-06-03 00:00:00.000
2011-07-21 00:00:00.000 2011-08-31 00:00:00.000
2011-10-24 00:00:00.000 2011-10-28 00:00:00.000
2011-12-19 00:00:00.000 2012-01-02 00:00:00.000
2012-02-13 00:00:00.000 2012-02-17 00:00:00.000
2012-04-02 00:00:00.000 2012-04-13 00:00:00.000
2012-06-04 00:00:00.000 2012-06-08 00:00:00.000
2012-07-20 00:00:00.000 2012-08-31 00:00:00.000
2012-10-29 00:00:00.000 2012-11-02 00:00:00.000
2012-12-24 00:00:00.000 2013-01-01 00:00:00.000
2013-02-10 00:00:00.000 2013-02-16 00:00:00.000
2013-03-24 00:00:00.000 2013-04-06 00:00:00.000
2013-05-26 00:00:00.000 2013-06-01 00:00:00.000
2013-07-24 00:00:00.000 2013-08-31 00:00:00.000
2013-10-27 00:00:00.000 2013-11-02 00:00:00.000
我需要从另一个表中选择上述任何范围内不存在日期戳的记录。
上表中的开始日期和结束日期可能相同,这表示只排除一天。
我最初的想法是扩展上述范围内的所有日期,然后执行SELECT WHERE NOT EXISTS IN,或者是否有更有效的方法来实现这一目标?
答案 0 :(得分:4)
SELECT t.*
FROM AnotherTable t
WHERE NOT EXISTS(
SELECT 1
FROM TblDate d
WHERE d.start_date <= t.DateColumn
AND d.end_date >= t.DateColumn
)
编辑:刚看到这是您最初的想法。所以我认为这是最简单,最快速的方法。以下是关于此主题的内容:
http://sqlserverperformance.idera.com/tsql-optimization/finding-nonexistent-records-hurry/
答案 1 :(得分:1)
您可以使用范围表进行左连接,并添加where子句,过滤掉任何匹配项。
SELECT anothertable.* FROM anothertable
LEFT JOIN range on anothertable.date >= range.start_date and anothertable.date <= range.end_date
WHERE range.start_date IS NULL
答案 2 :(得分:1)
以下内容比我的提案更有效(我认为)同样的最终结果。我唯一不确定的是,我是否理解了关于开始日期等于结束日期然后排除整天的标准。
SELECT *
FROM Table1
LEFT JOIN
( SELECT Start_date, CASE WHEN End_Date = Start_Date THEN DATEADD(MILLISECOND, -1, DATEADD(DAY, 1, End_Date)) ELSE End_Date END [End_Date]
FROM table2
) Exc
ON table.DateColumn BETWEEN Exc.Start_Date AND Exc.End_Date
WHERE Exc.Start_Date IS NULL
答案 3 :(得分:1)
您需要检查2个条件: 1.日期在范围之间 2.日期与start_date相同,但是当天晚些时候比end_date晚(你没有小时,分钟和秒)
SELECT * FROM VALUE_TABLE
LEFT JOIN DATE_RANGE_TABLE ON
YEAR(VALUE_TABLE.CHECK_DATE) = YEAR(start_date)
and MONTH (VALUE_TABLE.CHECK_DATE) = MONTH (start_date)
AND DAY (VALUE_TABLE.CHECK_DATE) = DAY (start_date)
OR VALUE_TABLE.CHECK_DATE BETWEEN start_date and end_date
WHERE start_date IS NULL
答案 4 :(得分:0)
select * from anothertable
WHERE NOT EXISTS (SELECT 1 FROM range
WHERE anothertable.date BETWEEN range.start_date AND range.end_date)
使用BETWEEN
代替<= and >=