teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

5

追記

2018/06/09 12:53

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -22,6 +22,10 @@
22
22
  ;
23
23
  ```
24
24
  #SQL
25
+
26
+ ・generate_series()で基準となる日付および一日の時間帯(range型)を生成
27
+ ・開始/終了のrange型で上記と結合
28
+ ※range型は範囲の上限下限の境界値を「含む/含めない」の指定ができかつ比較用の演算子もありますので、スケジュールなどのデータを扱うには非常に便利です。
25
29
  ```SQL
26
30
  with
27
31
  カレンダー as (

4

体裁

2018/06/09 12:53

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -65,17 +65,17 @@
65
65
  from generate_series('2018/6/8'::date,'2018/6/10'::date,'1 days') as w(日付)
66
66
  )
67
67
  , 予約状況 as(
68
- select *
68
+ select *
69
- , ('2018/' || 予約開始日 || ' ' || 予約開始時間)::timestamp 予約開始日時
69
+ , ('2018/' || 予約開始日 || ' ' || 予約開始時間)::timestamp 予約開始日時
70
- , ('2018/' || 予約終了予定日 || ' ' || 予約終了予定時間)::timestamp as 予定終了日時
70
+ , ('2018/' || 予約終了予定日 || ' ' || 予約終了予定時間)::timestamp as 予定終了日時
71
- from 予約データ
71
+ from 予約データ
72
72
  )
73
73
  , 日別状況 as (
74
- select 本,to_char(日付,'mm/dd') as 日付
74
+ select 本,to_char(日付,'mm/dd') as 日付
75
- , to_char(case when 日付> 予約開始日時 then 日付 else 予約開始日時 end,'hh24:mi') as 開始時刻
75
+ , to_char(case when 日付> 予約開始日時 then 日付 else 予約開始日時 end,'hh24:mi') as 開始時刻
76
- , to_char(case when 日付+'1 days'<予定終了日時 then 日付+'1 days'+'-1 second' else 予定終了日時 end,'hh24:mi') as 終了時刻
76
+ , to_char(case when 日付+'1 days'<予定終了日時 then 日付+'1 days'+'-1 second' else 予定終了日時 end,'hh24:mi') as 終了時刻
77
- from カレンダー clnd left join 予約状況 list
77
+ from カレンダー clnd left join 予約状況 list
78
- on clnd.日付範囲 && tsrange(list.予約開始日時,list.予定終了日時,'[)')
78
+ on clnd.日付範囲 && tsrange(list.予約開始日時,list.予定終了日時,'[)')
79
79
  )
80
80
  select 本
81
81
  , array_agg(日付 order by 日付) as 日付リスト

3

推敲

2018/06/09 05:41

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -85,6 +85,7 @@
85
85
  group by 本
86
86
  order by 本
87
87
  ```
88
+ #結果
88
89
  |本|日付リスト|開始時刻リスト|終了時刻リスト
89
90
  |:--|:--|:--|:--|
90
91
  本1|{06/08,06/08,06/09,06/09,06/10}|{12:00,18:00,00:00,13:00,00:00}|{18:00,23:59,12:00,23:59,18:00}

2

追記

2018/06/09 04:36

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -52,4 +52,40 @@
52
52
  本1|06/10|00:00|18:00
53
53
  本2|06/08|10:00|23:59
54
54
  本2|06/09|00:00|18:00
55
- 本2|06/10|10:00|18:00
55
+ 本2|06/10|10:00|18:00
56
+
57
+ #本コードごとに纏める
58
+ 本コード単位で日付、開始時刻、終了時刻を配列化しています。
59
+ 日付配列のループで添字を使って参照できるように、それぞれの配列は添え字が一致するようにしています。
60
+ ```SQL
61
+ with
62
+ カレンダー as (
63
+ select 日付::timestamp
64
+ , tsrange(日付::timestamp,(日付+'1 days')::timestamp,'[)') as 日付範囲
65
+ from generate_series('2018/6/8'::date,'2018/6/10'::date,'1 days') as w(日付)
66
+ )
67
+ , 予約状況 as(
68
+ select *
69
+ , ('2018/' || 予約開始日 || ' ' || 予約開始時間)::timestamp 予約開始日時
70
+ , ('2018/' || 予約終了予定日 || ' ' || 予約終了予定時間)::timestamp as 予定終了日時
71
+ from 予約データ
72
+ )
73
+ , 日別状況 as (
74
+ select 本,to_char(日付,'mm/dd') as 日付
75
+ , to_char(case when 日付> 予約開始日時 then 日付 else 予約開始日時 end,'hh24:mi') as 開始時刻
76
+ , to_char(case when 日付+'1 days'<予定終了日時 then 日付+'1 days'+'-1 second' else 予定終了日時 end,'hh24:mi') as 終了時刻
77
+ from カレンダー clnd left join 予約状況 list
78
+ on clnd.日付範囲 && tsrange(list.予約開始日時,list.予定終了日時,'[)')
79
+ )
80
+ select 本
81
+ , array_agg(日付 order by 日付) as 日付リスト
82
+ , array_agg(開始時刻 order by 日付, 開始時刻) as 開始時刻リスト
83
+ , array_agg(終了時刻 order by 日付, 開始時刻, 終了時刻) as 終了時刻リスト
84
+ from 日別状況
85
+ group by 本
86
+ order by 本
87
+ ```
88
+ |本|日付リスト|開始時刻リスト|終了時刻リスト
89
+ |:--|:--|:--|:--|
90
+ 本1|{06/08,06/08,06/09,06/09,06/10}|{12:00,18:00,00:00,13:00,00:00}|{18:00,23:59,12:00,23:59,18:00}
91
+ 本2|{06/08,06/09,06/10}|{10:00,00:00,10:00}|{23:59,18:00,18:00}

1

一部範囲修正

2018/06/09 04:34

投稿

sazi
sazi

スコア25430

answer CHANGED
@@ -39,7 +39,7 @@
39
39
  , to_char(case when 日付> 予約開始日時 then 日付 else 予約開始日時 end,'hh24:mi') as 開始時刻
40
40
  , to_char(case when 日付+'1 days'<予定終了日時 then 日付+'1 days'+'-1 second' else 予定終了日時 end,'hh24:mi') as 終了時刻
41
41
  from カレンダー clnd left join 予約状況 list
42
- on clnd.日付範囲 && tsrange(list.予約開始日時,list.予定終了日時,'[]')
42
+ on clnd.日付範囲 && tsrange(list.予約開始日時,list.予定終了日時,'[)')
43
43
  order by 本, 日付, 予約開始日時
44
44
  ```
45
45
  #結果