【问题标题】:Select all times (hour/minute) that occur within a set of small ranges bound by a large range - SQL 2000选择在由大范围限制的一组小范围内发生的所有时间(小时/分钟) - SQL 2000
【发布时间】:2012-05-13 12:20:00
【问题描述】:

我有一个包含索引数据的表,每一行都有一个开始和结束时间。查询此表并获取时间跨度在总体时间段内(通常是从 00:00:00 到 23:59:59 的一天)内的索引行列表很简单。

declare @date datetime, @start datetime, @end datetime

set @date = GetDate() //in production code this is a n input to a stored proc

//the date component of the current date/time, starting at midnight
set @start = DateAdd(dd, DateDiff(dd, 0, @date), 0) 

//one second before midnight the next day
set @end = DateAdd(dd, 1, DateAdd(ss, -1, @start)) 

select idx, start_time, end_time
from index_data
where start_time <= @end
and end_time >= @start
order by start_time 

结果会是这样的:

idx         start_time                  end_time
---------------------------------------------------------------
495640      2012-05-03 00:17:13.000     2012-05-03 00:17:45.000
495641      2012-05-03 00:18:20.000     2012-05-03 00:18:51.000
495642      2012-05-03 00:18:55.000     2012-05-03 00:19:31.000
495643      2012-05-03 00:34:08.000     2012-05-03 00:34:28.000
495644      2012-05-03 00:36:21.000     2012-05-03 00:36:41.000
495646      2012-05-03 01:22:21.000     2012-05-03 01:22:38.000
495647      2012-05-03 01:24:38.000     2012-05-03 01:24:55.000
495648      2012-05-03 01:30:11.000     2012-05-03 01:30:29.000
495649      2012-05-03 01:31:23.000     2012-05-03 01:31:39.000
495650      2012-05-03 02:09:57.000     2012-05-03 02:10:59.000
495651      2012-05-03 02:11:00.000     2012-05-03 02:11:00.000
495652      2012-05-03 02:14:25.000     2012-05-03 02:14:42.000
495653      2012-05-03 02:31:09.000     2012-05-03 02:31:25.000
495655      2012-05-03 03:02:32.000     2012-05-03 03:02:51.000
...

我需要的是一个高效查询(没有游标或其他循环),它将生成一个结果集,为给定一天的每一小时和每一分钟提供一行,至少一秒钟那一分钟的时间至少在一个索引的时间范围内:

hour   min
----------
0      17
0      18
0      19
0      34
0      36
1      22
1      24
1      30
1      31
2      9
2      10
2      11
2      14
2      31
3      02
...

每个索引的 start_time 和 end_time 通常相隔不到 60 秒(因此每分钟产生几行,因此希望合并以节省网络带宽),但我不能保证;某些行可能跨越更长的时间段,例如 start_time 为 02:20:34,end_time 为 02:23:43。给定这样的跨度,结果集必须包括 2:20、2:21、2:22 和 2:23,您不会通过将 start_time 查询与 end_time 查询联合起来得到。

关键在于:查询必须与 MSDE 引擎兼容,该引擎基本上是 MSS 2000。所以,没有 CTE(或者我已经这样做了)。

【问题讨论】:

    标签: sql datetime sql-server-2000


    【解决方案1】:

    如果 高效 是指最小 CPU 时间、读取次数等,那么您需要一个查找表。

    创建一个包含一天中所有 1440 分钟作为 DATETIME 的表。

    DECLARE
      @date  DATETIME,
      @start DATETIME,
      @end   DATETIME
    SELECT
      @date  = GetDate(),
      @start = DateAdd(dd, DateDiff(dd, 0, @date), 0),
      @end   = DateAdd(dd, 1, @start)
    
    SELECT
      minute_lookup.timestamp,
      COUNT(*)                    AS total_records
    FROM
      index_data
    INNER JOIN
      minute_lookup
        ON  minute_lookup.timestamp >= index_data.start_time - @date
        AND minute_lookup.timestamp <  index_data.end_time   - @date
    WHERE
          index_data.start_time < @end
      AND index_data.end_time   > @start
    GROUP BY
      minute_lookup.timestamp
    ORDER BY
      minute_lookup.timestamp
    

    实际上,您正在缓存一些计算。不要试图填补数据点之间的空白。


    关于日期时间边界的旁白

    另外,请注意我使用不同的 startend 值。

    如果我想涵盖一整天,我不会说2012-01-01 00:00:002012-01-01 23:59:59。如果表格在半秒后包含一个值怎么办?

    DateTimes 并不是真正的离散 值,它们是连续的。因此,我使用 FROM 2012-01-01 00:00:00 到但不包括 2012-01-02 00:00:00

    • x &gt;= '2012-01-01' AND x &lt; '2012-01-02'

    这样,无论 x 存储为什么级别的准确度,如果它代表 2012 年 1 月 1 日的任何内容,我都已捕获。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-08
    • 2018-12-28
    相关资源
    最近更新 更多