Pergunta

I'm looking to produce a count of projects based on 3 different conditions (DB2 database). I need to count all projects <= .10, >= .5, and >= 1.00 (percentage_used) but can only group by dim_building_id and building_name. Of course this query will not run because it requires percentage_used to be added to the group by. How do I handle those 3 conditions with percentage_used?

SELECT
SUM(CAST(FTS.GROUP_A AS BIGINT)) AS GROUP_A,
        SUM(CAST(FTS.GROUP_B AS BIGINT)) AS GROUP_B,
        SUM(CAST(FTS.GROUP_C AS BIGINT)) AS GROUP_C,


                CASE WHEN FAT.PERCENTAGE_USED <= '0.10'
                THEN COUNT(*)
                END AS PROJECTS_L10,
                CASE WHEN FAT.PERCENTAGE_USED >= '0.50' 
                THEN COUNT(*)
                END AS PROJECTS_G50,
                CASE WHEN FAT.PERCENTAGE_USED >= '1.00' 
                THEN COUNT(*)
                END AS PROJECTS_G100,
        DAYS(DATE('2014-07-01')) - DAYS(CURRENT DATE)  AS DAYS_LEFT,
        (DAYS(DATE('2014-07-01')) - DAYS(CURRENT DATE))/7 AS WEEKS_LEFT, 
        DAYS(DATE('2013-12-31')) - DAYS(CURRENT DATE) AS DAYS_LEFT_YEAR      

FROM FACT_TABLE AS FAT
INNER JOIN GROUPS AS FTS ON FAT.DIM_PROJECT_ID = FTS.DIM_PROJECT_ID
GROUP BY FAT.DIM_BUILDING_ID, FAT.BUILDING_NAME;
Foi útil?

Solução

I'd do something like this:

select bn.building_name ,
       t.*
from ( select fat.building_id ,
              sum( case when fat.percentage_used <= 0.10                                then 1 else 0 end ) as group_a ,
              sum( case when fat.percentage_used >  0.10 and fat.percentage_used < 0.50 then 1 else 0 end ) as group_b ,
              sum( case when fat.percentage_used >= 0.50 and fat.percentage_used < 1.00 then 1 else 0 end ) as group_c ,
              sum( case when fat.percentage_used >= 1.00                                then 1 else 0 end ) as group_d ,
              sum( case when fat.percentage_used is null                                then 1 else 0 end ) as group_e
       from fact_table fat
       join groups     fts on tfs.dim_project_id = fat.dim_project_id
       group by fat.building_id
     ) t
join fact_table bn on bn.building_id = t.building_id

Outras dicas

Instead of putting the aggregate as the THEN, wrap the CASE statement in an aggregate:

SELECT
SUM(CAST(FTS.GROUP_A AS BIGINT)) AS GROUP_A,
        SUM(CAST(FTS.GROUP_B AS BIGINT)) AS GROUP_B,
        SUM(CAST(FTS.GROUP_C AS BIGINT)) AS GROUP_C,  
        SUM(CASE WHEN FAT.PERCENTAGE_USED <= '0.10' THEN 1 ELSE 0 END) AS PROJECTS_L10,
        SUM(CASE WHEN FAT.PERCENTAGE_USED >= '0.50' THEN 1 ELSE 0 END) AS PROJECTS_G50,
        SUM(CASE WHEN FAT.PERCENTAGE_USED >= '1.00' THEN 1 ELSE 0 END) AS PROJECTS_G100,
        DAYS(DATE('2014-07-01')) - DAYS(CURRENT DATE)  AS DAYS_LEFT,
        (DAYS(DATE('2014-07-01')) - DAYS(CURRENT DATE))/7 AS WEEKS_LEFT, 
        DAYS(DATE('2013-12-31')) - DAYS(CURRENT DATE) AS DAYS_LEFT_YEAR      

FROM FACT_TABLE AS FAT
INNER JOIN GROUPS AS FTS ON FAT.DIM_PROJECT_ID = FTS.DIM_PROJECT_ID
GROUP BY FAT.DIM_BUILDING_ID, FAT.BUILDING_NAME;

The ELSE 0 isn't needed, but some like to see it in the query.

Alternatively this should work as well:

COUNT(CASE WHEN FAT.PERCENTAGE_USED >= '0.50' THEN 1 END) AS PROJECTS_G50,
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top