Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用重复的值透视表-可能吗?_Sql_Oracle_Excel_Vba - Fatal编程技术网

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