2

複数のエントリを持つテーブルがあります。1 つのエントリは、開始日時と終了日時で構成されます。

次のような方法でエントリのクラスターを見つけたい:

前のエントリが終了する前にエントリが開始された場合、両方がクラスタの一部です。ある種の重複問題です。

例:

id      start                    end
1       2007-04-11 15:34:02      2007-05-11 13:09:01
2       2007-06-13 15:42:39      2009-07-21 11:30:00
3       2007-11-26 14:30:02      2007-12-11 14:09:07
4       2008-02-14 08:52:11      2010-02-23 16:00:00

の出力が欲しい

id      start                    end
1       2007-04-11 15:34:02      2007-05-11 13:09:01
2-4     2007-06-13 15:42:39      2010-02-23 16:00:00

開始を並べ替えてから、行番号とラグ/リードなどを使用していくつかの計算を行うソリューションがありました。問題は、4 行目が 2 行目の直後に来る特殊なケースであるため、認識できません...

ここでSQLに良い解決策はありますか? 多分私は何かを逃していますか?

4

3 に答える 3

0

この質問に答えるために、新しいグループを開始する時刻を決定する必要があります。次に、毎回開始する前に、そのような開始の数を数えてグループを定義し、この値で集計します。

重複した時間がないと仮定すると、これはフラグを設定するために機能するはずです:

select e.*,
       (case when not exists (select 1
                              from entries e2
                              where e2.start < e.start and e2.end > e.start
                             )
             then 1 else 0
        end) as BeginsIsland
from entries e;

次に、SQL Server 2012+ を想定して、累積合計と集計を行います (これは以前のバージョンに簡単に適用できますが、コーディングは簡単です)。

with e as (
      select e.*,
             (case when not exists (select 1
                                    from entries e2
                                    where e2.start < e.start and e2.end > e.start
                                   )
                       then 1 else 0
              end) as BeginIslandFlag
      from entries e
     )
select (case when min(id) = max(id) then cast(max(id) as varchar(255))
             else cast(min(id) as varchar(255)) + '-' + cast(max(id) as varchar(255))
        end) as ids,
       min(start) as start, max(end) as end
from (select e.* sum(BeginIslandFlag) over (order by start) as grp
      from e
     ) e
group by grp;
于 2015-04-17T10:38:45.790 に答える