Sql 使用重复的值透视表-可能吗?
我有一个表-Sql 使用重复的值透视表-可能吗?,sql,oracle,excel,vba,Sql,Oracle,Excel,Vba,我有一个表-费率,如下所示: LOCATION_ID RATE_TYPE_CODE RATE_1 START_DATE END_DATE ----------- -------------- ---------- ---------- --------- 1 A .04 30-JUN-15 1 A .02 01-JUL-15 30-JUN-16
费率
,如下所示:
LOCATION_ID RATE_TYPE_CODE RATE_1 START_DATE END_DATE
----------- -------------- ---------- ---------- ---------
1 A .04 30-JUN-15
1 A .02 01-JUL-15 30-JUN-16
1 A 0 01-JUL-16
2 A .05 01-JUL-04
3 A .09 01-JUL-04
2 B .28 01-JUL-04 30-APR-16
2 B .34 01-MAY-16 30-APR-17
2 B .3 01-MAY-17
我必须从Excel工作簿宏查询此表,并根据位置ID以列格式获取费率,以日期范围分隔。因此,对于生效日期为2016年4月1日的1
我必须以Excel中的列式格式获得适用于2017年4月1日的费率:
我所尝试的:根据生效日期和一年后的时间获取正确的利率。以下是查询:
select *
from rate r
where ( r.start_date is null
or r.start_date <= to_date ('01-APR-2016')
or r.start_date >= to_date ('01-APR-2016')
and r.start_date <= add_months (to_date ('01-APR-2016'), 12))
and ( r.end_date is null
or r.end_date >= add_months (to_date ('01-APR-2016'), 12)
or r.end_date >= to_date ('01-APR-2016'));
我认为这样一个支点是可能的,但我看不出有什么办法。在此方面的任何帮助都将不胜感激。我找到了一个可以接受的答案:
with rate as
(select 1 location_id,
'A' rate_type_code,
0.04 rate_1,
null as start_date,
to_date ('30 JUN 2015') end_date
from dual
union all
select 1 location_id,
'A' rate_type_code,
0.02 rate_1,
to_date ('01 JUL 2015') as start_date,
to_date ('30 JUN 2016') end_date
from dual
union all
select 1,
'A',
0,
to_date ('01 JUL 2016'),
null
from dual
union all
select 2,
'A',
0.05,
to_date ('01 JUL 2004'),
null
from dual
union all
select 3,
'A',
0.09,
to_date ('01 JUL 2004'),
null
from dual
union all
select 2,
'B',
0.28,
to_date ('01 JUL 2004'),
to_date ('30 APR 2016')
from dual
union all
select 2,
'B',
0.34,
to_date ('01 MAY 2016'),
to_date ('30 APR 2017')
from dual
union all
select 2,
'B',
0.30,
to_date ('01 MAY 2017'),
null
from dual),
mod_rate as
(select r.location_id,
r.rate_type_code,
case
when nvl (r.start_date, to_date ('01-JAN-2000')) >
:my_start_date then
nvl (r.start_date, to_date ('01-JAN-2000'))
else
:my_start_date
end
as start_date,
case
when nvl (r.end_date, to_date ('31-DEC-2099')) <
nvl ( :my_end_date,
add_months ( :my_start_date, 12)) then
nvl (r.end_date, to_date ('31-DEC-2099'))
else
nvl ( :my_end_date, add_months ( :my_start_date, 12))
end
as end_date,
r.rate_1
from rate r
where ( r.start_date is null
or r.start_date <= :my_start_date
or r.start_date >= :my_start_date
and r.start_date <=
nvl ( :my_end_date,
add_months ( :my_start_date, 12)))
and ( r.end_date is null
or r.end_date >=
nvl ( :my_end_date,
add_months ( :my_start_date, 12))
or r.end_date >= :my_start_date)),
date_range as
( select mr.rate_type_code,
mr.start_date,
mr.end_date,
lead (
mr.start_date,
1)
over (partition by mr.rate_type_code
order by mr.rate_type_code, mr.start_date)
next_start_date
from mod_rate mr
group by mr.rate_type_code, mr.start_date, mr.end_date
order by mr.rate_type_code, mr.start_date, mr.end_date),
final_date_range as
(select dr.rate_type_code, dr.start_date, dr.end_date
from date_range dr
where not ( nvl (dr.next_start_date, dr.start_date) >
dr.start_date
and nvl (dr.next_start_date, dr.end_date) < dr.end_date))
select fdr.rate_type_code,
fdr.start_date,
fdr.end_date,
(select mr.rate_1
from mod_rate mr
where mr.rate_type_code = fdr.rate_type_code
and mr.start_date <= fdr.start_date
and mr.end_date >= fdr.end_date
and mr.location_id = 1)
as rates_for_location_1,
(select mr.rate_1
from mod_rate mr
where mr.rate_type_code = fdr.rate_type_code
and mr.start_date <= fdr.start_date
and mr.end_date >= fdr.end_date
and mr.location_id = 2)
as rates_for_location_2,
(select mr.rate_1
from mod_rate mr
where mr.rate_type_code = fdr.rate_type_code
and mr.start_date <= fdr.start_date
and mr.end_date >= fdr.end_date
and mr.location_id = 3)
as rates_for_location_3
from final_date_range fdr;
我可以在Excel中接收数据后简单地转换这些数据,并获得所需的格式
with rate as
(select 1 location_id,
'A' rate_type_code,
0.04 rate_1,
null as start_date,
to_date ('30 JUN 2015') end_date
from dual
union all
select 1 location_id,
'A' rate_type_code,
0.02 rate_1,
to_date ('01 JUL 2015') as start_date,
to_date ('30 JUN 2016') end_date
from dual
union all
select 1,
'A',
0,
to_date ('01 JUL 2016'),
null
from dual
union all
select 2,
'A',
0.05,
to_date ('01 JUL 2004'),
null
from dual
union all
select 3,
'A',
0.09,
to_date ('01 JUL 2004'),
null
from dual
union all
select 2,
'B',
0.28,
to_date ('01 JUL 2004'),
to_date ('30 APR 2016')
from dual
union all
select 2,
'B',
0.34,
to_date ('01 MAY 2016'),
to_date ('30 APR 2017')
from dual
union all
select 2,
'B',
0.30,
to_date ('01 MAY 2017'),
null
from dual),
mod_rate as
(select r.location_id,
r.rate_type_code,
case
when nvl (r.start_date, to_date ('01-JAN-2000')) >
:my_start_date then
nvl (r.start_date, to_date ('01-JAN-2000'))
else
:my_start_date
end
as start_date,
case
when nvl (r.end_date, to_date ('31-DEC-2099')) <
nvl ( :my_end_date,
add_months ( :my_start_date, 12)) then
nvl (r.end_date, to_date ('31-DEC-2099'))
else
nvl ( :my_end_date, add_months ( :my_start_date, 12))
end
as end_date,
r.rate_1
from rate r
where ( r.start_date is null
or r.start_date <= :my_start_date
or r.start_date >= :my_start_date
and r.start_date <=
nvl ( :my_end_date,
add_months ( :my_start_date, 12)))
and ( r.end_date is null
or r.end_date >=
nvl ( :my_end_date,
add_months ( :my_start_date, 12))
or r.end_date >= :my_start_date)),
date_range as
( select mr.rate_type_code,
mr.start_date,
mr.end_date,
lead (
mr.start_date,
1)
over (partition by mr.rate_type_code
order by mr.rate_type_code, mr.start_date)
next_start_date
from mod_rate mr
group by mr.rate_type_code, mr.start_date, mr.end_date
order by mr.rate_type_code, mr.start_date, mr.end_date),
final_date_range as
(select dr.rate_type_code, dr.start_date, dr.end_date
from date_range dr
where not ( nvl (dr.next_start_date, dr.start_date) >
dr.start_date
and nvl (dr.next_start_date, dr.end_date) < dr.end_date))
select fdr.rate_type_code,
fdr.start_date,
fdr.end_date,
(select mr.rate_1
from mod_rate mr
where mr.rate_type_code = fdr.rate_type_code
and mr.start_date <= fdr.start_date
and mr.end_date >= fdr.end_date
and mr.location_id = 1)
as rates_for_location_1,
(select mr.rate_1
from mod_rate mr
where mr.rate_type_code = fdr.rate_type_code
and mr.start_date <= fdr.start_date
and mr.end_date >= fdr.end_date
and mr.location_id = 2)
as rates_for_location_2,
(select mr.rate_1
from mod_rate mr
where mr.rate_type_code = fdr.rate_type_code
and mr.start_date <= fdr.start_date
and mr.end_date >= fdr.end_date
and mr.location_id = 3)
as rates_for_location_3
from final_date_range fdr;
RATE_TYPE_CODE START_DATE END_DATE RATES_FOR_LOCATION_1 RATES_FOR_LOCATION_2 RATES_FOR_LOCATION_3
-------------- ---------- ----------- -------------------- -------------------- --------------------
A 1/04/2016 30/06/2016 0.02 0.05 0.09
A 1/07/2016 1/04/2017 0 0.05 0.09
B 1/04/2016 30/04/2016 0.28
B 1/05/2016 1/04/2017 0.34