使用while循环执行选择查询以获取所有行值和计算列

时间:2016-09-29 15:27:31

标签: sql oracle plsql

我有一张表,其中包含客户代码,开始日期,结束日期以及客户在开始日期和结束日期之间的表现。我现在想要将这些性能数字重新设置为100,以便在SSRS图表中报告它们。在excel中很容易做到这一点但我不想在表上创建另一个字段并使用各自的重新基础值更新所有行。我编写了以下块来运行SSRS报告数据集,当我执行它时,我得到'没有找到数据' 。但我需要为我选择的客户重新设置13行。此外,我需要以查询格式(如下所示)输出,因为输出是用于SSRS图表。谢谢。

    DECLARE 
    i FLOAT(126) :=100;
    rowno number :=1; 
    n NUMBER;
    clicode VARCHAR(10);
    startdate DATE;
    enddate DATE;  
    performance FLOAT(126);
    month VARCHAR(10);
    year VARCHAR(10);  
    rebased_perf FLOAT(126);        
    BEGIN 
    select count(*) into n from performance;             
    WHILE rowno <= n LOOP
    select a.*,i*(1+(a.performance/100)) as rebased_perf into rowno,clicode,startdate,enddate,performance,month,year,rebased_perf from 
    (select rownum ,b.* from 
    (select clicode,startdate,enddate,performance,month,year from performance
    where period='Halfyearly'
    and clicode='XXX004'
    order by enddate) b )a 
    where rownum=rowno;
    i:=rebased_perf;
    rowno:=rowno+1;
    END LOOP;
  END; 

 CLICODE       STARTDATE    ENDDATE     PERFORMANCE  REBASED_PERF
 Startbase     05-Oct-09                             100
 XXX004        05-Oct-09    05-Apr-10   3.85         103.85
 XXX004        05-Apr-10    05-Oct-10   0.63         104.50
 XXX004        05-Oct-10    05-Apr-11   4.58         109.29
 XXX004        05-Apr-11    05-Oct-11   -8.07        100.47
 XXX004        05-Oct-11    05-Apr-12   8.13         108.63

2 个答案:

答案 0 :(得分:2)

纯SQL解决方案:

如果您的数据中有多个CLIcode(您可能会这样做,或者您没有该列),那么显示“startbase”而不是CLIcode的行是没有意义的。可以在enddateperformance中的NULL以及grow_of_100中的100中看到它是“基础”的事实。另外,我假设第一行是你的基础数据;它不应该是,它可以从其他行生成。根据需要进行调整。即使您需要某个应用程序中的输出,仍然最好运行纯SQL查询并仅将其输出导入您的应用程序。

with
     test_data ( clicode, startdate, enddate, performance ) as (
       select 'XXX004', date '2009-10-05', null             ,  null from dual union all
       select 'XXX004', date '2009-10-05', date '2010-04-05',  3.85 from dual union all
       select 'XXX004', date '2010-04-05', date '2010-10-05',  0.63 from dual union all
       select 'XXX004', date '2010-10-05', date '2011-04-05',  4.58 from dual union all
       select 'XXX004', date '2011-04-05', date '2011-10-05', -8.07 from dual union all
       select 'XXX004', date '2011-10-05', date '2012-04-05',  8.13 from dual
     )
--
-- end of test data; actual query begins here
select clicode, startdate, enddate, performance, 
       round(100 * exp( sum( ln(1 + nvl(performance,0) / 100) ) over
           (partition by clicode order by enddate asc nulls first) ), 2) as growth_of_100
from test_data
order by clicode, enddate asc nulls first
;


CLICODE STARTDATE ENDDATE   PERFORMANCE GROWTH_OF_100
------- --------- --------- ----------- -------------
XXX004  05-Oct-09                              100.00
XXX004  05-Oct-09 05-Apr-10        3.85        103.85
XXX004  05-Apr-10 05-Oct-10        0.63        104.50
XXX004  05-Oct-10 05-Apr-11        4.58        109.29
XXX004  05-Apr-11 05-Oct-11       -8.07        100.47
XXX004  05-Oct-11 05-Apr-12        8.13        108.64

6 rows selected.

答案 1 :(得分:0)

您无法以您想要的方式使用rownum。您应该直接使用游标或隐式循环:

DECLARE 
  i FLOAT(126) :=100;
  rebased_perf FLOAT(126);        
BEGIN 
  for x in (
     select a.*,i*(1+(a.performance/100)) as rebased_perf from (
              select clicode,startdate,enddate,performance,month,year from performance 
               where period='Halfyearly' and clicode='XXX004') a 
            order by enddate
  ) loop
    -- no more "into" rowno,clicode,startdate,enddate,performance,month,year,rebased_perf 
    --- but you can address the fields with "x.<field>"
    i:=x.rebased_perf;
    dbms_output.put_line('i='||i);
  END LOOP;
END;