删除SQL Server中时间范围内的记录

时间:2011-09-26 23:16:16

标签: sql sql-server tsql

我在TimeRanges表中有很多时间范围:

StartTime         EndTime
2010-01-01 06:00  2010-01-01 18:00
2010-01-01 20:00  2010-01-01 22:00
2010-01-02 06:00  2010-01-02 18:00
2010-01-02 20:00  2010-01-02 22:00
2010-01-03 06:00  2010-01-03 18:00
2010-01-03 20:00  2010-01-03 22:00
2010-01-04 06:00  2010-01-04 18:00
2010-01-04 20:00  2010-01-04 22:00
...
...
2010-02-01 06:00  2010-02-01 18:00
2010-02-01 20:00  2010-02-01 22:00
2010-02-02 06:00  2010-02-02 18:00
2010-02-02 20:00  2010-02-02 22:00
2010-02-03 06:00  2010-02-03 18:00
2010-02-03 20:00  2010-02-03 22:00
2010-02-04 06:00  2010-02-04 18:00
2010-02-04 20:00  2010-02-04 22:00
...
...
2011-01-01 06:00  2011-01-01 18:00
2011-01-01 20:00  2011-01-01 22:00
2011-01-02 06:00  2011-01-02 18:00
2011-01-02 20:00  2011-01-02 22:00
2011-01-03 06:00  2011-01-03 18:00
2011-01-03 20:00  2011-01-03 22:00
2011-01-04 06:00  2011-01-04 18:00
2011-01-04 20:00  2011-01-04 22:00
...
...
2011-02-01 06:00  2011-02-01 18:00
2011-02-01 20:00  2011-02-01 22:00
2011-02-02 06:00  2011-02-02 18:00
2011-02-02 20:00  2011-02-02 22:00
2011-02-03 06:00  2011-02-03 18:00
2011-02-03 20:00  2011-02-03 22:00
2011-02-04 06:00  2011-02-04 18:00
2011-02-04 20:00  2011-02-04 22:00

我在TimeFilters表中有一些过滤器:

StartTime         EndTime
2010-02-01 00:00  2010-03-01 00:00
2011-02-01 00:00  2011-03-01 00:00
2012-02-01 00:00  2012-03-01 00:00

我需要的是从TimeRanges表中删除记录,只保留TimeFilters表中的时间范围。

简单地说,我希望保留以下记录: 从2010-02-01 00:00到2010-03-01 00:00,如:

2010-02-01 06:00  2010-02-01 18:00
2010-02-01 20:00  2010-02-01 22:00
2010-02-02 06:00  2010-02-02 18:00
2010-02-02 20:00  2010-02-02 22:00
2010-02-03 06:00  2010-02-03 18:00
2010-02-03 20:00  2010-02-03 22:00
2010-02-04 06:00  2010-02-04 18:00
2010-02-04 20:00  2010-02-04 22:00

从2011-02-01 00:00到2011-03-01 00:00,如:

2011-02-01 06:00  2011-02-01 18:00
2011-02-01 20:00  2011-02-01 22:00
2011-02-02 06:00  2011-02-02 18:00
2011-02-02 20:00  2011-02-02 22:00
2011-02-03 06:00  2011-02-03 18:00
2011-02-03 20:00  2011-02-03 22:00
2011-02-04 06:00  2011-02-04 18:00
2011-02-04 20:00  2011-02-04 22:00

我现在可以做的是在TimeFilters中选择那些记录到临时表中,然后截断TimeRanges表,并从临时表中放回记录,但这非常耗时。

3 个答案:

答案 0 :(得分:3)

要删除TimeRangesTimeFilters中没有匹配项的所有记录,您可以

delete TimeRanges
  from TimeRanges r
  left join timefilters f on r.StartTime >= f.StartTime and r.EndTime <= f.EndTime 
 where f.StartTime is null

这里的棘手问题是执行left join,并删除那些没有对应过滤器的TimeRanges(当f.startTimef.endTime为空时)

删除后,您可以看到结果:

select *
  from TimeRanges

StartTime               EndTime
----------------------- -----------------------
2010-02-01 06:00:00.000 2010-02-01 18:00:00.000
2010-02-01 20:00:00.000 2010-02-01 22:00:00.000
2010-02-02 06:00:00.000 2010-02-02 18:00:00.000
2010-02-02 20:00:00.000 2010-02-02 22:00:00.000
2010-02-03 06:00:00.000 2010-02-03 18:00:00.000
2010-02-03 20:00:00.000 2010-02-03 22:00:00.000
2010-02-04 06:00:00.000 2010-02-04 18:00:00.000
2010-02-04 20:00:00.000 2010-02-04 22:00:00.000
2011-02-01 06:00:00.000 2011-02-01 18:00:00.000
2011-02-01 20:00:00.000 2011-02-01 22:00:00.000
2011-02-02 06:00:00.000 2011-02-02 18:00:00.000
2011-02-02 20:00:00.000 2011-02-02 22:00:00.000
2011-02-03 06:00:00.000 2011-02-03 18:00:00.000
2011-02-03 20:00:00.000 2011-02-03 22:00:00.000
2011-02-04 06:00:00.000 2011-02-04 18:00:00.000
2011-02-04 20:00:00.000 2011-02-04 22:00:00.000

(16 row(s) affected)

答案 1 :(得分:1)

你可以做的是一个外部联接,以获得匹配和不匹配,然后有一个条件来提取不匹配:

select * form TimeRanges r join TimeFilters f on
    r.StartTime between f.StartTime and f.EndTime and
    r.EndTime between f.StartTime and f.EndTime
where f.StartTime is null and f.EndTime is null

我不知道其余的是否可以用MySQL完成,但你要做的是生成一个条件,该条件匹配不在过滤表中日期之间的每一行。执行此操作的伪代码如下:

cond='';

while (r = read row) do
    if (cond=='') {
        sep='';
    } else {
        sep=' OR ';
    }

    cond = cond . sep .
        '(r.StartDate=' . r->StartDate . ' and r.EndDate=' . r->EndDate . ')';
}

# Before running the delete query comment it out and run the query printed by:
#  print 'select * from TimeRanges where '.cond;
run query 'delete from TimeRanges where '.cond;

如果使用MySql无法做到这一点,那么可以使用脚本语言来完成,例如PHP。

答案 2 :(得分:1)

我假设您的TimeRanges表上有某种ID列?如果是这样,这样的事情对你有用吗?

DELETE
    TimeRanges
WHERE
    id NOT IN ( SELECT
                    tr.id
                FROM
                    TimeRanges tr
                    JOIN TimeFilter tf ON tr.startdate >= tf.startdate AND
                                           tr.enddate <= tf.enddate )