我的数据进入我的系统(格式无法更改),如下所示:
Row, C001, C002, C003, to C029 (Columns for FY values)
1, Name, 0910, 1011
2, Eqt1 (Speed), 60, 100
3, Eqt1 (Cost), 20, 30
4, Eqt2 (Speed), 50, 60
5, Eqt2 (Cost), 30, 45
我需要将其更改为:
Name, Start_Date, End_Date, Speed, Cost
Eqt1, 01-APR-2009, 30-MAR-2010, 60, 20
Eqt1, 01-APR-2010, 30-MAR-2011, 100, 30
Eqt2, 01-APR-2009, 30-MAR-2010, 50, 30
Eqt2, 01-APR-2010, 30-MAR-2011, 60, 45
我可以使用子选择分割日期,其中row = 1。 我可以替换名称中的(速度)(成本)。 但我无法做到。
WITH survey_query AS (
SELECT *
FROM tbl_data
)
SELECT (CASE WHEN upper(sq.c001) LIKE '%FLEET SIZE%' THEN TRIM(REPLACE(upper(sq.c001), 'FLEET SIZE', ''))
WHEN upper(sq.c001) LIKE '%FLYING HOURS%' THEN TRIM(REPLACE(upper(sq.c001), 'FLYING HOURS', ''))
END) equipment_name
,(select TO_DATE(2000+dbms_lob.substr(c002,2,1)||'0101', 'yymmdd') FROM survey_query where line = 1) start_date
,(select TO_DATE(2000+dbms_lob.substr(c002,2,4)||'0330', 'yymmdd') FROM survey_query where line = 1) end_date
,(case when UPPER(sq.c001) like '%FLEET SIZE%' THEN sq.c002 END) fleet_size
,(case when UPPER(sq.c001) like '%FLYING HOURS%' THEN sq.c002 END) flying_hours
FROM survey_query sq
WHERE line > 1
UNION
SELECT (CASE WHEN upper(sq.c001) LIKE '%FLEET SIZE%' THEN TRIM(REPLACE(upper(sq.c001), 'FLEET SIZE', ''))
WHEN upper(sq.c001) LIKE '%FLYING HOURS%' THEN TRIM(REPLACE(upper(sq.c001), 'FLYING HOURS', ''))
END) equipment_name
,(select TO_DATE(2000+dbms_lob.substr(c003,2,1)||'0101', 'yymmdd') FROM survey_query where line = 1) start_date
,(select TO_DATE(2000+dbms_lob.substr(c003,2,4)||'0330', 'yymmdd') FROM survey_query where line = 1) end_date
,(case when UPPER(sq.c001) like '%FLEET SIZE%' THEN sq.c003 END) fleet_size
,(case when UPPER(sq.c001) like '%FLYING HOURS%' THEN sq.c003 END) flying_hours
FROM survey_query sq
WHERE line > 1;
有什么想法吗?我必须有一个更好的方法,因为我有28列的数据,所以27"工会"
由于
答案 0 :(得分:0)
它不是很优雅,因为它使用了旧式的旋转,但我无法通过11g PIVOT功能来解决这个问题:
with sample_data as (select 1 row#, 'Name' c001, 0910 c002, 1011 c003, 1112 c004 from dual union all
select 2 row#, 'Eqt1 (Speed)' c001, 60 c002, 100 c003, 140 c004 from dual union all
select 3 row#, 'Eqt1 (Cost)' c001, 20 c002, 30 c003, 80 c004 from dual union all
select 4 row#, 'Eqt2 (Speed)' c001, 50 c002, 60 c003, 70 c004 from dual union all
select 5 row#, 'Eqt2 (Cost)' c001, 30 c002, 45 c003, 56 c004 from dual),
-- end of mimicking your table as a subquery called "sample_data"
-- you wouldn't need this subquery, since you would have your own table/query to use in place
-- change the table name referred to in the res subquery below as appropriate
res as (select row#,
case when c001 like '%(Speed)' then substr(c001, 1, length(c001) - 8)
when c001 like '%(Cost)' then substr(c001, 1, length(c001) - 7)
else c001
end name,
case when c001 like '%(Speed)' then 'Speed'
when c001 like '%(Cost)' then 'Cost'
else c001
end type,
to_date('01/04'||substr(first_value(lpad(c002, 4, 0)) over (order by row#), 1, 2), 'dd/mm/rr') fy1_start_date,
to_date('31/03'||substr(first_value(lpad(c002, 4, 0)) over (order by row#), 3, 2), 'dd/mm/rr') fy1_end_date,
to_date('01/04'||substr(first_value(lpad(c003, 4, 0)) over (order by row#), 1, 2), 'dd/mm/rr') fy2_start_date,
to_date('31/03'||substr(first_value(lpad(c003, 4, 0)) over (order by row#), 3, 2), 'dd/mm/rr') fy2_end_date,
to_date('01/04'||substr(first_value(lpad(c004, 4, 0)) over (order by row#), 1, 2), 'dd/mm/rr') fy3_start_date,
to_date('31/03'||substr(first_value(lpad(c004, 4, 0)) over (order by row#), 3, 2), 'dd/mm/rr') fy3_end_date,
c002,
c003,
c004
from sample_data),
dummy as (select level id
from dual
connect by level <= 3 -- num fyears to consider
)
select name,
case when d.id = 1 then res.fy1_start_date
when d.id = 2 then res.fy2_start_date
when d.id = 3 then res.fy3_start_date
end start_date,
case when d.id = 1 then res.fy1_end_date
when d.id = 2 then res.fy2_end_date
when d.id = 3 then res.fy3_end_date
end end_date,
max(case when d.id = 1 and res.type = 'Speed' then c002
when d.id = 2 and res.type = 'Speed' then c003
when d.id = 3 and res.type = 'Speed' then c004
end) speed,
max(case when d.id = 1 and res.type = 'Cost' then c002
when d.id = 2 and res.type = 'Cost' then c003
when d.id = 3 and res.type = 'Cost' then c004
end) cost
from res
cross join dummy d
where res.row# != 1
group by name,
case when d.id = 1 then res.fy1_start_date
when d.id = 2 then res.fy2_start_date
when d.id = 3 then res.fy3_start_date
end,
case when d.id = 1 then res.fy1_end_date
when d.id = 2 then res.fy2_end_date
when d.id = 3 then res.fy3_end_date
end
order by name, start_date;
NAME START_DATE END_DATE SPEED COST
----- ----------- ----------- ---------- ----------
Eqt1 01-APR-2009 31-MAR-2010 60 20
Eqt1 01-APR-2010 31-MAR-2011 100 30
Eqt1 01-APR-2011 31-MAR-2012 140 80
Eqt2 01-APR-2009 31-MAR-2010 50 30
Eqt2 01-APR-2010 31-MAR-2011 60 45
Eqt2 01-APR-2011 31-MAR-2012 70 56
答案 1 :(得分:0)
感谢您的回答,他们让我思考。也很抱歉在回复中等了很长时间,我已经工作了2周。
我已经离开了以下
str.replaceAll("\\p{Blank}+", "").replaceAll("[\\.\\*\\?]+", ".*?");