2017-02-22 9 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, хотя это VARCHAR представляет собой число в месяц . iE 2 равно февральскому, а 3 - маршу и т. д.) до жесткого числа 14. Поэтому, внимательно изучив данные, вы заметите, что в 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; 

но в итоге я получаю кучу нулей и некоторые странные результаты.

+0

Итак, что вы пытались? – OldProgrammer

+0

@OldProgrammer Я добавил свою попытку ниже вопроса – Miguel

+1

Несколько вещей, которые я не понимаю ... Если FP должен быть месяцем (2 = февраль), то почему он проходит через 14, а не через 12? Возможно, FY предназначен для представления года, и вам нужно, чтобы «счет» продлился до февраля следующего года? Или что? И другой вопрос, если вам нужен «текущий счет», разделённый FY, FP, Fund и Type, почему подсчет для FY = 12 начинается со значения 10, а затем остается постоянным в 10? Это ни подсчет, ни сумма, и, похоже, это не «подсчет». (Я предполагаю, что вы хотите работать с SUM, а не с COUNT, но вам все равно нужно объяснять) – mathguy

ответ

1

Это не может быть самым эффективным решением, но его легко понять и поддерживать. Сначала (в самом глубоко вложенном подзапросе) мы находим min FP для каждой комбинации FY, FUND и TYPE. Затем мы используем запрос CONNECT BY для заполнения всех FP для всех комбинаций FY, FUND, TYPE (до жесткого верхнего предела 14). Затем мы оставили-external-join в исходные данные в таблице 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

надеюсь, вы все еще смотрите на этот вопрос. В FY16 есть одна небольшая проблема. Я не вижу периода 1-4 на выходе. Я пытался его настроить, но я никуда не денусь, никаких идей? – Miguel

+0

@ Мигель - Я не понимаю. Ваше объяснение, а также ваша таблица «желаемых результатов» показывают, что для каждой комбинации FY, FUND и TYPE результаты будут включать FP только от самого низкого значения до жесткого кодированного значения 14. Для FY = 12 ваш данные имеют только одну строку с FP = 05, поэтому значения будут FP от 05 до 14 - зачем вам нужно 01 до 04? (Изменилось ли требование? Или было неправильно начинать? И если это так, то все равно, в любом случае, для 15 и 16, почему только за 12?) – mathguy