您的位置:首页 > 数据库 > Oracle

Asktom Oracle:How to multiplex single row into multiple rows

2011-08-11 10:03 543 查看
Hi Tom,

First of all, thanks for your tremendous contribution to the
Oracle Community in helping people like us solve day to day Oracle replated
problems.

I have a small problem. Here are the details:

CREATE
TABLE T
(
HS_ID NUMBER(20) PRIMARY KEY,
HS_NM VARCHAR2(30
BYTE),
HS_STRT_DT DATE,
HS_END_DT DATE,
HS_CLT_IND CHAR(1 BYTE)

);

Insert into TMS.T
(HS_ID, HS_NM, HS_STRT_DT, HS_END_DT, HS_CLT_IND)
Values
(1, 'Alaska', TO_DATE('01/01/2004 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/31/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 'N');
Insert into TMS.T
(HS_ID, HS_NM, HS_STRT_DT, HS_END_DT, HS_CLT_IND)
Values
(2, 'Alabama', TO_DATE('01/01/2003 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/31/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 'Y');
Insert into TMS.T
(HS_ID, HS_NM, HS_STRT_DT, HS_END_DT, HS_CLT_IND)
Values
(3, 'Virginia', TO_DATE('01/01/2001 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/31/2004 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 'N');
Insert into TMS.T
(HS_ID, HS_NM, HS_STRT_DT, HS_END_DT, HS_CLT_IND)
Values
(4, 'Virginia', TO_DATE('01/01/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/31/2012 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), 'Y');
COMMIT;
Here is the business rule:

For each row in table t, view should traslate
it into multiple rows based on start, end date and current year
(HS_STRT_DT , HS_END_DT).

Taking example of row with id=1:

strt_dt=01/01/2004
end_dt=12/31/2012
current_year=2007

If
current_year <= end_dt then the row should get translated into 4 rows, one
for each year starting 2004 and ending at 2007.
If current_year > end_dt
then that particular row should have (year(end_dt)-strt_dt) rows,
starting at year(strt_dt) and ending at year(strt_dt)

Thanks in
advance for your time and help.

and we said...

You might have to play around
with some boundary value conditions - just to validate that the math is right -
don't know your data like you know it, but here is the idea, I used 100 as the
max year spread, you can adjust based on your needs

ops$tkyte%ORA10GR2> select * from t;

HS_ID HS_NM                          HS_STRT_D HS_END_DT H
---------- ------------------------------ --------- --------- -
1 Alaska                         01-JAN-04 31-DEC-12 N
2 Alabama                        01-JAN-03 31-DEC-12 Y
3 Virginia                       01-JAN-01 31-DEC-04 Y
4 Virginia                       01-JAN-05 31-DEC-12 N

WITH data
AS (    SELECT LEVEL - 1 l
FROM DUAL
CONNECT BY LEVEL <= 100)
SELECT hs_id,
hs_nm,
TO_CHAR (ADD_MONTHS (hs_strt_dt, l * 12), 'yyyy'),
hs_clt_ind
FROM t, data
WHERE l <
CEIL (MONTHS_BETWEEN (LEAST (SYSDATE, hs_end_dt), hs_strt_dt) / 12)
AND TO_CHAR (ADD_MONTHS (hs_strt_dt, l * 12), 'yyyy') <=
TO_CHAR (SYSDATE, 'yyyy')
ORDER BY 1, 2, 3
HS_ID HS_NM                          TO_C H
---------- ------------------------------ ---- -
1 Alaska                         2004 N
1 Alaska                         2005 N
1 Alaska                         2006 N
1 Alaska                         2007 N
2 Alabama                        2003 Y
2 Alabama                        2004 Y
2 Alabama                        2005 Y
2 Alabama                        2006 Y
2 Alabama                        2007 Y
3 Virginia                       2001 Y
3 Virginia                       2002 Y
3 Virginia                       2003 Y
3 Virginia                       2004 Y
4 Virginia                       2005 N
4 Virginia                       2006 N
4 Virginia                       2007 N

16 rows selected.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: