4

次のようなテーブルがあります。

CREATE TABLE #TEMP (Name VARCHAR(255), START_TIME datetime, END_TIME datetime);

INSERT INTO #TEMP VALUES('John', '2012-01-01 09:00:01', '2012-01-01 12:00:02')
INSERT INTO #TEMP VALUES('John', '2012-01-01 09:40:01', '2012-01-01 11:00:02')
INSERT INTO #TEMP VALUES('John', '2012-01-02 05:00:01', '2012-01-02 05:15:02')
INSERT INTO #TEMP VALUES('David', '2012-01-04 05:00:01', '2012-01-04 05:15:02')
INSERT INTO #TEMP VALUES('David', '2012-01-05 07:01:01', '2012-01-05 15:15:02')

SELECT *
FROM #TEMP

DROP TABLE #TEMP

データは次のとおりです。

     Name   START_TIME                 END_TIME
1    John   2012-01-01 09:00:01.000    2012-01-01 12:00:02.000
2    John   2012-01-01 09:40:01.000    2012-01-01 11:00:02.000
3    John   2012-01-02 05:00:01.000    2012-01-02 05:15:02.000
4    David  2012-01-04 05:00:01.000    2012-01-04 05:15:02.000
5    David  2012-01-05 07:01:01.000    2012-01-05 08:15:02.000

GROUP BY6 という数字が与えられた場合、このテーブルで を実行し、前後の 6 時間のウィンドウ内で重複する時間をマージしようとしています。したがって、上記の表では、時間範囲が重複しているため、行1と行2が 1 つの行にマージされます。

John 2012-01-01 06:00:01.000 2012-01-01 18:00:02.000

45は、 から 6 時間を引く07:01:01.000と行 のウィンドウに収まるため、マージされます4

約100万行を含む大きなテーブルでこれを行う良い方法はありますか?

4

1 に答える 1

2

これを行う最善の方法は、テーブルを作成し、windows#temp テーブルとこの新しいウィンドウ テーブルを結合することだと思います。

1) ステップ 1、考えられるすべてのウィンドウ ギャップ (重複するウィンドウを含む) を含むウィンドウ テーブルを準備します。

   SELECT 
      Name,
      dateadd(hour, -6, start_time) as start_w, 
      dateadd(hour, +6, start_time) as end_w
   into #possible_windows
   FROM #TEMP 

2) 一時テーブルにインデックスを作成してパフォーマンスを向上させる

   create index pw_idx on #possible_windows ( Name, start_w)

3) 自己結合選択で重複するウィンドウを削除します。これがインデックスを作成する理由です。

   select p2.* 
   into #myWindows
   from #possible_windows p1
   right outer join #possible_windows p2
     on p1.name = p2.name and 
        p2.start_w > p1.start_W and p2.start_w <= p1.end_w
   where p1.name is null

4) テーブルを #myWindows で結合するか、直接使用します。

働く:

SELECT 
  Name,
  dateadd(hour, -6, start_time) as start_w, 
  dateadd(hour, +6, start_time) as end_w,
  ROW_NUMBER() over(partition by Name order by Name, 
                    dateadd(hour, -6, start_time) ) as rn
into #possible_windows
FROM #TEMP 

create index pw_idx on #possible_windows ( Name, start_w)

select p2.* 
from #possible_windows p1
right outer join #possible_windows p2
  on p1.name = p2.name and 
     p2.start_w > p1.start_W and p2.start_w <= p1.end_w
where p1.name is null

結果:

Name  start_w       end_w         rn 
----- ------------- ------------- -- 
David 2012-01-03 23:00:012012-01-04 11:00:011  
David 2012-01-05 01:01:012012-01-05 13:01:012  
John  2012-01-01 03:00:012012-01-01 15:00:011  
John  2012-01-01 23:00:012012-01-02 11:00:013 

PE: パフォーマンス テストに戻ってください!

于 2012-05-12T14:24:59.183 に答える