2017-02-22 226 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