質問

I'm getting duplicates when I self join on my fact table. What I'm looking to do is join on the fact table twice to produce some aggregate totals. My sql results are returning duplicate projects only when I join on the fact table for the percentage and production aggregates. There may be a better way to do this. I'm up for suggestions. (DB2)

SELECT distinct
DP.PROJECT_ID,
DP.PROJECT_NAME,
DM.BUILDING_NAME,
DA.AMOUNT,
cast(sum(cast(FAT.TRANSACTION_AMOUNT as real)) as integer) as GROSS,
(DA.AMOUNT - sum(FAT.TRANSACTION_AMOUNT)) as NET,
PERCENT.PERCENTAGE_USED,
PROD.PRODUCTION


FROM FACT_TABLE as FAT
    RIGHT JOIN ALCF_WAREHOUSE.DIM_A DA ON FAT.DIM_A_ID = DA.DIM_A_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_PROJECT DP ON FAT.DIM_PROJECT_ID = DP.DIM_PROJECT_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE DD ON FAT.START_DATE_DIM_ID = DD.DATE_KEY
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE T3 ON FAT.END_DATE_DIM_ID = T3.DATE_KEY
    INNER JOIN ALCF_WAREHOUSE.DIM_JOB DJ ON FAT.DIM_JOB_ID = DJ.DIM_JOB_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_BUILDING DM ON FAT.BUILDING_ID = DM.BUILDING_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE T5 ON DJ.JOB_END_ID = T5.DATE_KEY
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE T10 ON DJ.JOB_START_ID = T10.DATE_KEY
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE DDS on DDS.DATE_KEY = DA.A_START_DATE_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE DDE on DDE.DATE_KEY = DA.A_END_DATE_ID

    JOIN
    (
            SELECT DP.DIM_PROJECT_ID,
                concat(((sum(FAT.TRANSACTION_AMOUNT)/DA.AMOUNT)*100),'%') AS Percentage_used
                FROM FACT_TABLE as FAT
                INNER JOIN DIM_A DA ON FAT.DIM_A_ID = DA.DIM_A_ID
                INNER JOIN DIM_PROJECT DP ON FAT.DIM_PROJECT_ID = DP.DIM_PROJECT_ID
                WHERE DA.BUILDING_NAME IN ('MAIN', 'SECONDARY')
                    AND DA.TYPE_NAME = 'INVISION'
                GROUP BY DP.DIM_PROJECT_ID, DA.AMOUNT
                HAVING concat(((sum(FAT.TRANSACTION_AMOUNT)/DA.AMOUNT)*100),'%') <> '.00%'
            ) percent on DP.dim_project_id = percent.dim_project_id

      JOIN
      (
            SELECT DJ.DIM_PROJECT_ID, cast(sum(cast(FAT.TRANSACTION_AMOUNT as real)) as integer) as PRODUCTION
                FROM FACT_TABLE as FAT  
                RIGHT OUTER JOIN DIM_A DA ON FAT.DIM_A_ID = DA.DIM_A_ID
                INNER JOIN DIM_JOB DJ ON FAT.DIM_JOB_ID = DJ.DIM_JOB_ID                    
                WHERE DJ.SIZE in ('33% <= x <= 100%', '16% <= x < 33%')
                    AND DA.BUILDING_NAME IN ('MAIN', 'SECONDARY')
                    AND DA.TYPE_NAME = 'INVISION'
                GROUP BY DJ.DIM_PROJECT_ID
            ) PROD on DP.dim_project_id = PROD.dim_project_id 


WHERE
        ((DD.DATE_VALUE >= '2013-01-01'
        AND T3.DATE_VALUE <= '2014-01-01')
        OR (((DD.DATE_VALUE > '2013-01-01'
        AND DD.DATE_VALUE < '2014-01-01')
        OR (T3.DATE_VALUE <= '2014-01-01'
        AND T3.DATE_VALUE > '2013-01-01')
        OR (DD.DATE_VALUE <= '2013-01-01'
        AND T3.DATE_VALUE > '2014-01-01'))
        AND (T5.DATE_VALUE >= '2013-01-01'
        AND T5.DATE_VALUE < '2014-01-01')))
        AND DM.BUILDING_NAME IN ('MAIN', 'SECONDARY')
        AND DA.TYPE_NAME = 'INVISION'
        AND DDS.YEAR4 = '2013'

GROUP BY
    DP.DIM_PROJECT_ID,
    DP.PROJECT_NAME,
    DM.MACHINE_NAME,
    DA.AMOUNT,
    PERCENT.PERCENTAGE_USED,
    PROD.PRODUCTION

 ORDER BY PROJECT_NAME

Results of query above: enter image description here

Desired results: enter image description here

役に立ちましたか?

解決

I discovered that the having clause was really not needed so I was able to remove a table join for the percentage aggregation and calculate the percentage outside a self join. This removed the duplicates.

SELECT distinct
DP.PROJECT_ID,
DP.PROJECT_NAME,
DM.BUILDING_NAME,
DA.AMOUNT,
cast(sum(cast(FAT.TRANSACTION_AMOUNT as real)) as integer) as GROSS,
(DA.AMOUNT - sum(FAT.TRANSACTION_AMOUNT)) as NET,
concat(((sum(FAT.TRANSACTION_AMOUNT)/DA.AMOUNT)*100),'%') AS Percentage_used,
PROD.PRODUCTION

FROM FACT_TABLE as FAT
    RIGHT JOIN ALCF_WAREHOUSE.DIM_A DA ON FAT.DIM_A_ID = DA.DIM_A_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_PROJECT DP ON FAT.DIM_PROJECT_ID = DP.DIM_PROJECT_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE DD ON FAT.START_DATE_DIM_ID = DD.DATE_KEY
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE T3 ON FAT.END_DATE_DIM_ID = T3.DATE_KEY
    INNER JOIN ALCF_WAREHOUSE.DIM_JOB DJ ON FAT.DIM_JOB_ID = DJ.DIM_JOB_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_BUILDING DM ON FAT.BUILDING_ID = DM.BUILDING_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE T5 ON DJ.JOB_END_ID = T5.DATE_KEY
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE T10 ON DJ.JOB_START_ID = T10.DATE_KEY
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE DDS on DDS.DATE_KEY = DA.A_START_DATE_ID
    INNER JOIN ALCF_WAREHOUSE.DIM_DATE DDE on DDE.DATE_KEY = DA.A_END_DATE_ID

    JOIN
      (
            SELECT DJ.DIM_PROJECT_ID, cast(sum(cast(FAT.TRANSACTION_AMOUNT as real)) as integer) as PRODUCTION
                FROM FACT_TABLE as FAT  
                RIGHT OUTER JOIN DIM_A DA ON FAT.DIM_A_ID = DA.DIM_A_ID
                INNER JOIN DIM_JOB DJ ON FAT.DIM_JOB_ID = DJ.DIM_JOB_ID                    
                WHERE DJ.SIZE in ('33% <= x <= 100%', '16% <= x < 33%')
                    AND DA.BUILDING_NAME IN ('MAIN', 'SECONDARY')
                    AND DA.TYPE_NAME = 'INVISION'
                GROUP BY DJ.DIM_PROJECT_ID
            ) PROD on DP.dim_project_id = PROD.dim_project_id 


WHERE
        ((DD.DATE_VALUE >= '2013-01-01'
        AND T3.DATE_VALUE <= '2014-01-01')
        OR (((DD.DATE_VALUE > '2013-01-01'
        AND DD.DATE_VALUE < '2014-01-01')
        OR (T3.DATE_VALUE <= '2014-01-01'
        AND T3.DATE_VALUE > '2013-01-01')
        OR (DD.DATE_VALUE <= '2013-01-01'
        AND T3.DATE_VALUE > '2014-01-01'))
        AND (T5.DATE_VALUE >= '2013-01-01'
        AND T5.DATE_VALUE < '2014-01-01')))
        AND DM.BUILDING_NAME IN ('MAIN', 'SECONDARY')
        AND DA.TYPE_NAME = 'INVISION'
        AND DDS.YEAR4 = '2013'

GROUP BY
    DP.DIM_PROJECT_ID,
    DP.PROJECT_NAME,
    DM.MACHINE_NAME,
    DA.AMOUNT,
    PROD.PRODUCTION

 ORDER BY PROJECT_NAME
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top