Sorry,
I made a mistake. I'm a little trigger happy with that SEND button.
This is corrected and should give you the actual days and approximate months and years at the institution.
SQL> SELECT unvl_id,
institution_cd,
from_date,
thru_date
FROM ( SELECT unvl_id,
institution_cd,
range_from_date from_date,
LAST_VALUE( range_thru_date ignore nulls ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY range_from_date DESC )
thru_date
FROM ( SELECT unvl_id,
institution_cd,
from_date,
thru_date,
CASE
WHEN LAG( thru_date ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY from_date,
thru_date ) BETWEEN from_date
AND thru_date
AND LAG( thru_date ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY from_date,
thru_date ) IS NOT NULL
THEN NULL
ELSE from_date
END range_from_date,
CASE
WHEN LEAD( from_date ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY from_date,
thru_date ) BETWEEN from_date
AND thru_date
AND LEAD( from_date ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY from_date,
thru_date ) IS NOT NULL
THEN NULL
ELSE thru_date
END range_thru_date
FROM ( SELECT aa.unvl_id,
aa.institution_cd,
aa.from_date,
NVL( aa.thru_date, TRUNC( SYSDATE ))
thru_date
FROM academic_appointment aa,
academic_appointment aa_b
WHERE aa.institution_cd = aa_b.institution_cd(+)
AND aa.unvl_id = aa_b.unvl_id(+)
AND aa.from_date >= aa_b.from_date(+)
AND NVL( aa.thru_date, TRUNC( SYSDATE )) <=
NVL( aa_b.thru_date(+),
TRUNC( SYSDATE ))
AND aa.ROWID != aa_b.ROWID(+)
AND aa_b.ROWID IS NULL )))
WHERE from_date IS NOT NULL
ORDER BY 1,
2,
3,
4
UNVL_ID INSTITUTION_CD FROM_DATE THRU_DATE
---------- -------------- --------- ---------
101 INSTITUTION_CD 21-JAN-98 27-FEB-02
101 INSTITUTION_CD 28-FEB-02 15-JUL-05
102 INSTITUTION_CD 13-MAY-01 24-NOV-06
114 INSTITUTION_CD 24-JUL-06 11-OCT-07
122 INSTITUTION_CD 01-MAY-07 11-OCT-07
176 INSTITUTION_CD 24-JUL-06 30-APR-07
176 INSTITUTION_CD 01-MAY-07 11-OCT-07
200 INSTITUTION_CD 17-JAN-96 17-OCT-01
200 INSTITUTION_CD 01-NOV-02 30-APR-07
201 INSTITUTION_CD 17-JUN-04 11-OCT-07
10 rows selected.
SQL> SELECT unvl_id,
institution_cd,
SUM( (thru_date - from_date) + 1 ) days,
ROUND( SUM( (thru_date - from_date) + 1 ) /( 365 / 12 ), 1 ) months,
ROUND( SUM( (thru_date - from_date) + 1 ) /( 365 ), 1 ) years
FROM (
SELECT unvl_id,
institution_cd,
from_date,
thru_date
FROM ( SELECT unvl_id,
institution_cd,
range_from_date from_date,
LAST_VALUE( range_thru_date ignore nulls ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY range_from_date DESC )
thru_date
FROM ( SELECT unvl_id,
institution_cd,
from_date,
thru_date,
CASE
WHEN LAG( thru_date ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY from_date,
thru_date ) BETWEEN from_date
AND thru_date
AND LAG( thru_date ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY from_date,
thru_date ) IS NOT NULL
THEN NULL
ELSE from_date
END range_from_date,
CASE
WHEN LEAD( from_date ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY from_date,
thru_date ) BETWEEN from_date
AND thru_date
AND LEAD( from_date ) OVER( PARTITION BY unvl_id, institution_cd ORDER BY from_date,
thru_date ) IS NOT NULL
THEN NULL
ELSE thru_date
END range_thru_date
FROM ( SELECT aa.unvl_id,
aa.institution_cd,
aa.from_date,
NVL( aa.thru_date, TRUNC( SYSDATE ))
thru_date
FROM academic_appointment aa,
academic_appointment aa_b
WHERE aa.institution_cd = aa_b.institution_cd(+)
AND aa.unvl_id = aa_b.unvl_id(+)
AND aa.from_date >= aa_b.from_date(+)
AND NVL( aa.thru_date, TRUNC( SYSDATE )) <=
NVL( aa_b.thru_date(+),
TRUNC( SYSDATE ))
AND aa.ROWID != aa_b.ROWID(+)
AND aa_b.ROWID IS NULL )))
WHERE from_date IS NOT NULL
)
GROUP BY unvl_id,
institution_cd
ORDER BY 1,
2,
3,
4
UNVL_ID INSTITUTION_CD DAYS MONTHS YEARS
---------- -------------- ---------- ---------- ----------
101 INSTITUTION_CD 2733 89.9 7.5
102 INSTITUTION_CD 2022 66.5 5.5
114 INSTITUTION_CD 445 14.6 1.2
122 INSTITUTION_CD 164 5.4 .4
176 INSTITUTION_CD 445 14.6 1.2
200 INSTITUTION_CD 3743 123.1 10.3
201 INSTITUTION_CD 1212 39.8 3.3
7 rows selected.