【SQL】期間が重なるデータを取得するには

■ はじめに

例えば、ユーザが、From-Toで期間を選択して
その期間内のデータをSQLで取得する方法について考える

目次

【1】期間が重なるデータを取得するには
 1)図解
 2)SQL構文
 3)マトリックス(期待値)
【2】サンプル
 1)SQL文

 【1】期間が重なるデータを取得するには

期間

from : 2011/11/01 - To : 2011/11/30

テーブルデー

下記のような期間が重なるデータを取得するSQL文を考える。

id | startDate  | endDate   |
---+------------+------------+
 0 | 2011/10/29 | 2011/10/30 | => X
---+------------+------------+
 1 | 2011/11/02 | 2011/11/30 | => ○
---+------------+------------+
 2 | 2011/12/01 | 2011/12/02 | => X
---+------------+------------+
 3 | 2011/11/29 | 2011/12/02 | => ○

 1)図解

表の見方

  10/30  10/31   11/01  11/02  ....   11/29  11/30  12/01  12/02
----+------+-------+<=====+=============+=====>+------+------+------------->

 * 「開始日(startDate)=10/30」「終了日(endDate)=10/31」は、11/01-11/30に重ならない
    |<====>|

 * 「開始日(startDate)=10/31」「終了日(endDate)=12/01」は、11/0-11/30と重なる
           |<========================================>|

 2)SQL構文

SELECT * FROM 【テーブル名】
WHERE 【ユーザから選択from】 <= 【テーブル名】.endDate
 AND  【ユーザから選択To】   >= 【テーブル名】.startDate

 3)マトリックス(期待値)

「from : 2011/11/01 - To : 2011/11/30」の場合

                                     終了日(endDate)
                       |10/30|10/31|11/01|11/02|11/29|11/30|12/01|12/02|
-----------------+-----+-----+-----+-----+-----+-----+-----+-----+-----+
開始日(startDate)|10/30|  x  |  x  |  o  |  o  |  o  |  o  |  o  |  o  |
                 |10/31|  -  |  x  |  o  |  o  |  o  |  o  |  o  |  o  |
                 |11/01|  -  |  -  |  o  |  o  |  o  |  o  |  o  |  o  |
                 |11/02|  -  |  -  |  -  |  o  |  o  |  o  |  o  |  o  |
                 |11/29|  -  |  -  |  -  |  -  |  o  |  o  |  o  |  o  |
                 |11/30|  -  |  -  |  -  |  -  |  -  |  o  |  o  |  o  |
                 |12/01|  -  |  -  |  -  |  -  |  -  |  -  |  x  |  x  |
                 |12/02|  -  |  -  |  -  |  -  |  -  |  -  |  -  |  x  |

[説明]

 x : 期間が重ならないデータ
 o : 期間が重なるデータ
 - : 終了日(To)が開始日(From)を超えて現実的にありえないため、テスト不要

 【2】サンプル

 テーブル

CREATE TABLE [TermSample](
    [id] [int] NULL,
    [Name] [nvarchar](50) NULL,
    [startDate] [date] NULL,
    [endDate] [date] NULL
) ON [PRIMARY]

 サンプルデータ

0    X-001   2011-10-29  2011-10-30
1   O-001   2011-11-02  2011-11-30
2   X-002   2011-12-01  2011-12-02
3   O-002   2011-11-29  2011-12-02

 1)SQL

SELECT *
  FROM TermSample
  WHERE '2011/11/01' <= endDate
 AND  '2011/11/30' >= startDate

 出力

id   Name    startDate   endDate
1   O-001   2011-11-02  2011-11-30
3   O-002   2011-11-29  2011-12-02

関連記事

サブクエリ / 副問合せ
https://dk521123.hatenablog.com/entry/2015/12/21/002727
順位付け・ランキング ~ RANK / DENSE_RANK ~
https://dk521123.hatenablog.com/entry/2012/08/15/225233