41135
お世話になります。

SQL(MicrosoftAccess)で、異なる二つの期間のレコードがある場合、一つにつなげた  
期間として結果を求める書き方を教えてください。

よろしくお願いいたします。

[![画像の説明をここに入力](https://i.stack.imgur.com/yXxaG.jpg)](https://i.stack.imgur.com/yXxaG.jpg)
CC BY-SA 3.0
2018-01-22T06:36:40.057
41132
2018-01-22T12:22:05.590
9374
question
sql
SQLで重なる二つの期間がある場合に、一つにつなげた期間を求める方法
実用的かは知りませんが以下の要領で実現できると思います。

まず`start`と`end`を1つの列にまとめ、区別のために`1`と`-1`の符号を振ります。

```

    SELECT 1 Type, start Date from table
    UNION ALL
    SELECT -1, end from table
    
```

結果

```

     1 2013-03-01
     1 2013-05-01
     1 2013-06-01
    -1 2013-07-10
    -1 2013-07-31
    -1 2013-08-30
     1 2013-09-15
     1 2013-10-01
    -1 2013-11-30
    -1 2013-12-31
    
```

次にこの結果セットをType,Dateの昇順に並べてTypeの和を求めます。

```

    SELECT a.Type, a.Date
         , (SELECT SUM(b.Type)
              FROM set1 b
             WHERE b.Date < a.Date
                OR (b.Date = a.Date AND b.Type <= a.Type)) RunningTotal
    FROM set1 a
    
```

結果

```

     1 2013-03-01 1
     1 2013-05-01 2
     1 2013-06-01 3
    -1 2013-07-10 2
    -1 2013-07-31 1
    -1 2013-08-30 0
     1 2013-09-15 1
     1 2013-10-01 2
    -1 2013-11-30 1
    -1 2013-12-31 0
    
```

この数字は該当日付から次の日付までの区間で何個のレコードが重なっているかを表しています。求めたいのは1個以上のレコードが存在する区間ですので`0→1`と`1→0`の変動を抽出すればよく、つまり`(Type,
RunningTotal)`が`(1, 1)`～`(-1, 0)`の間を探せばよいです。

```

    SELECT a.Date Start
         , (SELECT MIN(b.Date)
              FROM set2 b
             WHERE Type = -1
               AND RunningTotal = 0
               AND b.Date > a.Date) End
      FROM set2 a
     WHERE Type = 1 AND RunningTotal = 1
    
```
CC BY-SA 3.0
2018-01-22T12:22:05.590
41135
2018-01-22T12:22:05.590
5750
41132
answer