3

各行に開始時刻と終了時刻があるインデックス データを含むテーブルがあります。このテーブルにクエリを実行して、タイムスパンが包括的な期間 (通常は 00:00:00 から 23:59:59 までの 1 日) 内にあるインデックス行のリストを取得するのは簡単です。

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
...

私が必要としているのは、その日の少なくとも 1 秒が少なくとも 1 つのインデックスの時間内に収まる、指定された日の各時間と分ごとに行を提供する結果セットを生成する効率的なクエリ (カーソルやその他のループなし) です。範囲:

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 秒未満です (したがって、1 分間に数行が生成されるため、ネットワーク帯域幅を節約するために統合する必要があります) が、それを保証することはできません。たとえば、start_time が 02:20:34 で end_time が 02:23:43 のように、一部の行はより長い期間にまたがることがあります。このようなスパンが与えられた場合、結果セットには 2:20、2:21、2:22、および 2:23 が含まれている必要があります。これは、start_time のクエリと end_time のクエリを UNIONing しても得られません。

キッカーは次のとおりです。クエリは、基本的に MSS 2000 である MSDE エンジンと互換性がある必要があります

4

1 に答える 1

2

効率的に、最小CPU時間、読み取りなどを意味する場合は、ルックアップテーブルが必要です。

1日の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

事実上、計算の一部をキャッシュしています。データポイント間のギャップを埋めようとはしません。


DateTime境界の脇

また、開始値と終了値の使用方法が異なることに注意してください。

一日をカバーしたいのなら、私は言いませ2012-01-01 00:00:002012-01-01 23:59:59。その0.5秒後にテーブルに値が含まれている場合はどうなりますか?

DateTimesは実際には離散値ではなく、連続しています。そのため、私はFROMを使用します2012-01-01 00:00:00が、除外します。2012-01-02 00:00:00

  • x >= '2012-01-01' AND x < '2012-01-02'

このように、どのレベルの精度xが格納されていても、それが2012年1月1日の何かを表す場合、私はそれをキャプチャしました。

于 2012-05-03T23:36:27.567 に答える