添加行,运行计数,运行总和以查询结果

时间:2017-02-22 02:02:15

标签: sql oracle

我有一张包含以下ddl的表格。

 CREATE TABLE "LEDGER" 
   ("FY" NUMBER, 
    "FP" VARCHAR2(20 BYTE), 
    "FUND" VARCHAR2(20 BYTE), 
    "TYPE" VARCHAR2(2 BYTE), 
    "AMT" NUMBER
   )

该表包含以下数据。

REM INSERTING into LEDGER
SET DEFINE OFF;
Insert into LEDGER (FY,FP,FUND,TYPE,AMT) values (15,'03','A','03',1);
Insert into LEDGER (FY,FP,FUND,TYPE,AMT) values (15,'04','A','03',2);
Insert into LEDGER (FY,FP,FUND,TYPE,AMT) values (16,'04','A','03',3);
Insert into LEDGER (FY,FP,FUND,TYPE,AMT) values (12,'05','A','04',6);

基于fy,fp,基金和类型的分区我想写一个查询来保持从fp开始的运行计数(fp虽然它是一个varchar,它代表一个月中的数字.iE 2等于因此,如果仔细查看数据,您会注意到,在FY 15中,最长期限为04,因此我必须在报告中再添加10个期间才能将报告提交给我的报告。有完整的14个时期。这是预期的输出。 enter image description here

这是我尝试过的,但我只是简单地在这上面磕磕绊绊。

WITH    fy_range    AS
(
    SELECT  MIN (fy)  AS min_fy
    ,       MAX (fy)  AS max_fy
    FROM   ledger
),all_fys AS
(
    SELECT  min_fy + LEVEL - 1  AS fy
    FROM    fy_range
    CONNECT BY  LEVEL <= max_fy + 1 - min_fy
)
,all_fps    AS
(
    SELECT  TO_CHAR (LEVEL, 'FM00')  AS fp
    FROM    dual
    CONNECT BY  LEVEL  <= 14  
)   

SELECT 
 FUND
 ,G.TYPE
 ,G.FY
 ,G.FP
 ,LAST_VALUE(G.AMT ignore nulls) OVER (PARTITION BY G.FUND ORDER BY Y.FY P.FP ) AS AMT
 FROM             all_fys   y
 CROSS JOIN       all_fps   p
 LEFT OUTER JOIN LEDGER G PARTITION BY(FUND)
                                  ON   g.fy  = y.fy
                                  AND  g.fp  = p.fp;

但我最终得到了一堆空值和一些奇怪的结果。

1 个答案:

答案 0 :(得分:1)

这可能不是最有效的解决方案,但它易于理解和维护。首先(在最深层次嵌套的子查询中),我们为FPFYFUND的每个组合找到最小TYPE。然后,我们使用CONNECT BY查询来填充所有FP组合的所有FY, FUND, TYPE(最高为14的硬上限)。然后我们将左外连接到LEDGER表中的原始数据。到目前为止,我们致密数据。在最终查询(连接)中,我们还添加累积和的列 - 在我们将数据加密后,该部分很容易。

TYPE是Oracle关键字,因此最好不要将其用作列名。最好不要使用双引号表和列名(由于这个原因我不得不使用大写字母)。我还确保从varchar2转换为number并返回varchar2 - 我们不应该依赖隐式转换。

select S.FY, to_char(S.FP, 'FM09') as FP, S.FUND, S.TYPE,
       sum(L.AMT) over (partition by S.FY, S.FUND, S.TYPE order by S.FP) as CUMULATIVE_AMT
from   (
         select FY, MIN_FP + level - 1 as FP, FUND, TYPE
         from   (
                  select   FY, min(to_number(FP)) as MIN_FP, FUND, TYPE
                  from     LEDGER
                  group by FY, FUND, TYPE
                )
         connect by level <= 15 - MIN_FP
             and prior FY   = FY
             and prior FUND = FUND
             and prior TYPE = TYPE
             and prior sys_guid() is not null
       ) S left outer join LEDGER L 
           on S.FY = L.FY and S.FP = L.FP and S.FUND = L.FUND and S.TYPE = L.TYPE
;

<强>输出

FY FP  FUND TYPE CUMULATIVE_AMT
--- --- ---- ---- --------------
 12 05  A    04                6
 12 06  A    04                6
 12 07  A    04                6
 12 08  A    04                6
 12 09  A    04                6
 12 10  A    04                6
 12 11  A    04                6
 12 12  A    04                6
 12 13  A    04                6
 12 14  A    04                6
 15 03  A    03                1
 15 04  A    03                3
 15 05  A    03                3
 15 06  A    03                3
 15 07  A    03                3
 15 08  A    03                3
 15 09  A    03                3
 15 10  A    03                3
 15 11  A    03                3
 15 12  A    03                3
 15 13  A    03                3
 15 14  A    03                3
 16 04  A    03                3
 16 05  A    03                3
 16 06  A    03                3
 16 07  A    03                3
 16 08  A    03                3
 16 09  A    03                3
 16 10  A    03                3
 16 11  A    03                3
 16 12  A    03                3
 16 13  A    03                3
 16 14  A    03                3