2017-02-22 144 views
0

我有一个表格以下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等于二月,三等于三月等)到14的硬数。因此,仔细查看数据,您会注意到在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; 

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

+0

那么你有什么企图? – OldProgrammer

+0

@OldProgrammer我在问题 – Miguel

+1

下面添加了我的尝试,我不明白......如果FP应该是一个月(2 = 2月),那么它为什么会穿过14而不是12穿过?也许风云旨在代表一年,你需要“计数”来贯穿次年的二月?或者是什么?另一个问题是,如果你需要一个由FY,FP,Fund和Type划分的“跑步数”,为什么FY = 12的计数从10开始,然后保持在10?这既不是一个数字,也不是一笔数额,它似乎不是一个“跑步”数。 (我假设你想要一个正在运行的SUM,而不是COUNT,但是你需要更多地解释) – mathguy

回答

1

这可能不是最有效的解决方案,但它很容易理解和维护。首先(在嵌套最深的子查询中),我们找到FY,FUNDTYPE的每个组合的最小FP。然后,我们使用CONNECT BY查询来填充所有FY, FUND, TYPE组合的所有FP(达到硬件上限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 
+0

很好的解释!我一直坚持几天试图刷新这一点!感谢百万人的回答! – Miguel

+0

希望你仍然在看这个问题。在2016财年有一个小问题,我没有看到产出的1-4期。我一直在试图调整它,但我没有得到任何想法? – Miguel

+0

@Miguel - 我不明白。您的解释以及您自己的“期望结果”表显示,对于FY,FUND和TYPE的每种组合,结果将包括FP仅从最低值到硬编码值14。对于FY = 12,您的数据只有一行,FP = 05,所以这些值将从05到14的FP - 为什么你需要01到04? (需求是否改变?或者开始时是否错误?如果是这样,反正15和16,为什么只是12?) – mathguy