あなたはこのようなことをすることができます:
with family_ranges(familyid, min_start, max_end, curr_date)
as (select familyid,
min(startdate),
max(enddate),
to_number(to_char(min(startdate), 'j'))
from family
group by familyid
union all
select familyid, min_start, max_end, curr_date+1
from family_ranges
where curr_date < to_number(to_char(max_end,'j')))
select familyid, min(curr_date) fromdate, max(curr_date) todate, state
from (select familyid, to_date(curr_date,'j') curr_date,
case when head = 'Y' and partner = 'Y' and child = 'Y' then 'Family'
when head = 'Y' and partner = 'Y' then 'Couple'
when head = 'Y' and child = 'Y' then 'SingleParent'
when head = 'Y' then 'Single'
end state
from (select f.familyid, d.curr_date, f.relationship
from family_ranges d
inner join family f
on f.familyid = d.familyid
and to_date(d.curr_date,'j') between f.startdate and f.enddate)
pivot (
max('Y')
for relationship in ('Head' as head, 'Partner' as partner, 'Child' as child)
))
group by familyid, state
order by familyid, fromdate;
日付->ジュリアンでナンセンスを許してください。因数分解されたサブクエリで日付演算が失敗する11.2.0.1-3のバグを回避することです。
fatoredサブクエリ部分は、ファミリがまたがる日付のリストを取得します。それから私たちはそれを家族に戻し、その日に家族の中にいた人を見つけ出します。
select f.familyid, d.curr_date, f.relationship
from family_ranges d
inner join family f
on f.familyid = d.familyid
and to_date(d.curr_date,'j') between f.startdate and f.enddate;
ここで、これをピボットして単純なY/Nリストを取得します
SQL> with family_ranges(familyid, min_start, max_end, curr_date)
2 as (select familyid,
3 min(startdate),
4 max(enddate),
5 to_number(to_char(min(startdate), 'j'))
6 from family
7 group by familyid
8 union all
9 select familyid, min_start, max_end, curr_date+1
10 from family_ranges
11 where curr_date < to_number(to_char(max_end,'j')))
12 select familyid, to_date(curr_date,'j') curr_date, head, partner, child
13 from (select f.familyid, d.curr_date, f.relationship
14 from family_ranges d
15 inner join family f
16 on f.familyid = d.familyid
17 and to_date(d.curr_date,'j') between f.startdate and f.enddate)
18 pivot (
19 max('Y')
20 for relationship in ('Head' as head, 'Partner' as partner, 'Child' as child)
21 );
FAMILYID CURR_DATE H P C
---------- --------- - - -
1 09-NOV-12 Y
1 11-NOV-12 Y
1 13-NOV-12 Y
1 23-NOV-12 Y
2 23-NOV-12 Y
2 28-NOV-12 Y Y
2 29-NOV-12 Y Y
1 30-NOV-12 Y Y
1 01-DEC-12 Y Y
1 03-DEC-12 Y Y
2 18-DEC-12 Y Y Y
2 20-DEC-12 Y Y Y
次に、ルールから必要な文字列を取得し、日付範囲を取得するためにグループ化するという単純なケースです。
SQL> with family_ranges(familyid, min_start, max_end, curr_date)
2 as (select familyid,
3 min(startdate),
4 max(enddate),
5 to_number(to_char(min(startdate), 'j'))
6 from family
7 group by familyid
8 union all
9 select familyid, min_start, max_end, curr_date+1
10 from family_ranges
11 where curr_date < to_number(to_char(max_end,'j')))
12 select familyid, min(curr_date) fromdate, max(curr_date) todate, state
13 from (select familyid, to_date(curr_date,'j') curr_date,
14 case when head = 'Y' and partner = 'Y' and child = 'Y' then 'Family'
15 when head = 'Y' and partner = 'Y' then 'Couple'
16 when head = 'Y' and child = 'Y' then 'SingleParent'
17 when head = 'Y' then 'Single'
18 end state
19 from (select f.familyid, d.curr_date, f.relationship
20 from family_ranges d
21 inner join family f
22 on f.familyid = d.familyid
23 and to_date(d.curr_date,'j') between f.startdate and f.enddate)
24 pivot (
25 max('Y')
26 for relationship in ('Head' as head, 'Partner' as partner, 'Child' as child)
27 ))
28 group by familyid, state
29 order by familyid, fromdate;
FAMILYID FROMDATE TODATE STATE
---------- --------- --------- ------------
1 05-NOV-12 24-NOV-12 Single
1 25-NOV-12 14-DEC-12 Couple
1 15-DEC-12 24-JAN-13 Family
1 25-JAN-13 13-FEB-13 SingleParent
2 05-NOV-12 24-NOV-12 Single
2 25-NOV-12 14-DEC-12 Couple
2 15-DEC-12 13-FEB-13 Family
フィドル:http ://sqlfiddle.com/#!4 / 484b5 / 1