改进Oracle查询,将月度因子应用于每月预算值的查询

时间:2017-08-02 18:36:58

标签: sql oracle

这是实现我目标的蛮力方式,但可能有更有效的方式

SELECT sum(jan/(SELECT JAN FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_JAN,  
       sum(feb/(SELECT FEB FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_FEB,  
       sum(mar/(SELECT MAR FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_MAR,  
       sum(apr/(SELECT APR FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_APR,  
       sum(may/(SELECT MAY FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_MAY,  
       sum(jun/(SELECT JUN FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_JUN,  
       sum(jul/(SELECT JUL FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_JUL,  
       sum(aug/(SELECT AUG FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_AUG,  
       sum(sep/(SELECT SEP FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_SEP,  
       sum(oct/(SELECT OCT FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_OCT,  
       sum(nov/(SELECT NOV FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_NOV,  
       sum(dec/(SELECT DEC FROM MONTHLY_FACTORS WHERE YEAR = '2017')) as FACTORED_DEC,  
       sum( 
                jan/(SELECT JAN FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                feb/(SELECT FEB FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                mar/(SELECT MAR FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                apr/(SELECT APR FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                may/(SELECT MAY FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                jun/(SELECT JUN FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                jul/(SELECT JUL FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                aug/(SELECT AUG FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                sep/(SELECT SEP FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                oct/(SELECT OCT FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                nov/(SELECT NOV FROM MONTHLY_FACTORS WHERE YEAR = '2017') + 
                dec/(SELECT DEC FROM MONTHLY_FACTORS WHERE YEAR = '2017')  
                ) as FACTORED_YEAR_TOTAL 
                FROM MONTHLY_BUDGET  
                WHERE DEPT = '123ABC' AND YEAR = '2017' 

MONTHLY_FACTORS表格如

YEAR JAN FEB ... DEC
2016   3   2 ...   4
2017 ...

MONTHLY_BUDGET表格如

YEAR DEPT    JAN     FEB   ...  DEC
2016 123abc  50234   20032      22234
2017 123abc  ...
2016 xyz456  40054   23002 ...  44442

预期输出看起来像

YEAR    JAN/JAN_FACTOR     FEB/FEB_FACTOR   ...  DEC/DEC_FACTOR

没有所有子查询,是否有更简洁的方式?

2 个答案:

答案 0 :(得分:0)

/* Formatted on 8/2/2017 11:07:39 PM (QP5 v5.287) */
WITH a
     AS (  SELECT year,
                  SUM (jan) jan,
                  SUM (feb) feb,
                  SUM (mar) mar,
                  SUM (apr) apr,
                  SUM (may) may,
                  SUM (jun) jun,
                  SUM (jul) jul,
                  SUM (aug) aug,
                  SUM (sep) sep,
                  SUM (oct) oct,
                  SUM (nov) nov,
                  SUM (dec) dec
             FROM MONTHLY_BUDGET
            WHERE DEPT = '123abc' and year= 2017
         GROUP BY dept, year),
     b
     AS (SELECT JAN,
                FEB,
                MAR,
                APR,
                MAY,
                JUN,
                JUL,
                AUG,
                SEP,
                OCT,
                NOV,
                DEC,
                year
           FROM MONTHLY_FACTORS where year = 2017)
SELECT a.jan / b.JAN,
       a.feb / b.FEB,
       a.mar / b.mar,
       a.apr / b.apr,
       a.may / b.may,
       a.jun / b.jun,
       a.jul / b.jul,
       a.aug / b.aug,
       a.sep / b.sep,
       a.oct / b.oct,
       a.nov / b.nov,
       a.dec / b.dec
  FROM a, b
 WHERE a.year = b.year

以上查询不是一个好的解决方案,但更简单。

注意:从MONTHLY_BUDGET中选择* select *,其中DEPT ='123ABC'AND YEAR ='2017'语句返回一行或多行。如果你保证它返回一行,不要在'with a'子句中使用'sum'。

另一方面,我们可以为您的案例编写一个函数。

答案 1 :(得分:0)

我首先要解开表格,以便你有年/月行。意见对此有用。如果您可以向数据库添加视图,那很好。如果没有,您可以将这些转换为内联视图。

我使用M01代表Jan,M02代表2月。但这些只是标签,你可以使用你想要的任何东西。

    CREATE OR REPLACE VIEW tmp_MF
AS
WITH
     MF AS
        (
        SELECT
             TO_CHAR(Year)      AS Year
            ,TO_CHAR(M01)       AS M01
            ,TO_CHAR(M02)       AS M02
            ,TO_CHAR(M03)       AS M03
            ,TO_CHAR(M04)       AS M04
            ,TO_CHAR(M05)       AS M05
            ,TO_CHAR(M06)       AS M06
            ,TO_CHAR(M07)       AS M07
            ,TO_CHAR(M08)       AS M08
            ,TO_CHAR(M09)       AS M09
            ,TO_CHAR(M10)       AS M10
            ,TO_CHAR(M11)       AS M11
            ,TO_CHAR(M12)       AS M12
        FROM tmp_Monthly_Factors                mf
        )
SELECT
     Year
    ,"Value"
    ,"Month"
FROM mf
UNPIVOT
    (
    "Value"
    FOR "Month" IN (M01,M02,M03,M04,M05,M06,M07,M08,M09,M10,M11,M12)
    )
;

CREATE OR REPLACE VIEW tmp_MB
AS
    WITH
     MB AS
        (
        SELECT
             TO_CHAR(mb.Year)       AS Year
            ,Dept
            ,TO_CHAR(M01)       AS M01
            ,TO_CHAR(M02)       AS M02
            ,TO_CHAR(M03)       AS M03
            ,TO_CHAR(M04)       AS M04
            ,TO_CHAR(M05)       AS M05
            ,TO_CHAR(M06)       AS M06
            ,TO_CHAR(M07)       AS M07
            ,TO_CHAR(M08)       AS M08
            ,TO_CHAR(M09)       AS M09
            ,TO_CHAR(M10)       AS M10
            ,TO_CHAR(M11)       AS M11
            ,TO_CHAR(M12)       AS M12
        FROM tmp_Monthly_Budget             mb
        )
SELECT
     Year
    ,Dept
    ,"Month"
    ,"Value"
FROM mb
UNPIVOT
    (
    "Value"
    FOR "Month" IN (M01,M02,M03,M04,M05,M06,M07,M08,M09,M10,M11,M12)
    )
;

然后我认为PIVOT查询会为您提供所需的结果。这可能需要稍微调整,但应该接近:

    WITH 
     Pivot_Data AS
        (
        SELECT
             tmp_MB.Year
            ,tmp_MB.Dept
            ,tmp_MB."Month"
    --      ,tmp_MB."Value" AS Budget_Value
    --      ,tmp_MF."Value" AS Monthly_Factor
            ,ROUND(tmp_MB."Value" / tmp_MF."Value",2) AS Month_Value
        FROM tmp_MB
            --
            JOIN tmp_MF
                ON  tmp_MF.Year   = tmp_MB.Year
                AND tmp_MF."Month" = tmp_MB."Month"
        WHERE (1 = 1)
    --    AND tmp_MB.Year = 2016
        )
SELECT
     Year
    ,Dept
    ,"Jan"  AS "Factored Jan"
    ,"Feb"
    ,"Mar"
    ,"Apr"
    ,"May"
    ,"Jun"
    ,"Jul"
    ,"Aug"
    ,"Sep"
    ,"Oct"
    ,"Nov"
    ,"Dec"
    ,"Jan" + "Feb" + "Mar" + "Apr" + "May" + "Jun" + "Jul" + "Aug" + "Sep" + "Oct" + "Nov" + "Dec" AS "Factored Year Total"
FROM Pivot_Data
PIVOT
    (
    MAX(Month_Value) FOR "Month" IN
        (
         'M01'      AS "Jan"
        ,'M02'      AS "Feb"
        ,'M03'      AS "Mar"
        ,'M04'      AS "Apr"
        ,'M05'      AS "May"
        ,'M06'      AS "Jun"
        ,'M07'      AS "Jul"
        ,'M08'      AS "Aug"
        ,'M09'      AS "Sep"
        ,'M10'      AS "Oct"
        ,'M11'      AS "Nov"
        ,'M12'      AS "Dec"
        )
    )
ORDER BY Year, Dept
;