Search code examples
sql-server-2008coalesce

Show 0 Not Null With Pivot


Why is my Coalesce() statement in my initial Select statement not replacing the Null with a 0?

Select * From
(
    Select a.orderstatus As [Stat], Coalesce(Count(b.id), '0') As [Count], b.region
    From orderstatus a
    Left Join saleinfo b
    on b.orderstatus = a.orderstatus
    Group By a.orderstatus, b.region
) one
    pivot ( Max([Count]) For region In ([East], [West], [North], [South]) ) pv

Solution

  • Because you are using it in the inner query, whereas the problem is that the record doesn't it exist so the PIVOT is creating the NULL after the inner query has been processed. If your query (one) returned:

    Stat    Count   Region
    -------------------------
    Stat1   0       East
    Stat2   2       East
    Stat1   5       West
    

    You will end up with a Pivot Table like

    Stat    East    West    North   South
    ---------------------------------------
    Stat1   0       5       NULL    NULL
    Stat2   2       NULL    NULL    NULL
    

    For example you get NULL for (Stat2, West) because there is no result in your subquery, so the COALESCE does not help. Your work around would be to just use COUNT in the PIVOT itself:

    SELECT  pvt.OrderStatus, pvt.East, pvt.West, pvt.North, pvt.South
    FROM    (   SELECT  os.OrderStatus, si.Region, si.ID
                FROM    OrderStatus AS os
                        LEFT JOIN SaleInfo AS si
                            ON si.OrderStatus = b.OrderStatus
            ) AS t
            PIVOT
            (   COUNT(ID)
                FOR Region IN ([East], [West], [North], [South])
            ) AS pvt;
    

    Or to put the COALESCE in the outer select:

    SELECT  pvt.OrderStatus, 
            East = COALESCE(pvt.East, 0), 
            West = COALESCE(pvt.West, 0), 
            North = COALESCE(pvt.North, 0), 
            South = COALESCE(pvt.South, 0)
    FROM    (   SELECT  os.OrderStatus, si.Region, [Count] = COUNT(si.ID)
                FROM    OrderStatus AS os
                        LEFT JOIN SaleInfo AS si
                            ON si.OrderStatus = b.OrderStatus
            ) AS t
            PIVOT
            (   MAX([Count])
                FOR Region IN ([East], [West], [North], [South])
            ) AS pvt;
    

    I much prefer the first option though.


    EDIT

    Example showing 0 returned for non existent data when using COUNT:

    SELECT  pvt.Stat, pvt.East, pvt.West, pvt.North, pvt.South
    FROM    (VALUES
                ('Stat1', 'East', 1),
                ('Stat2', 'East', 2),
                ('Stat1', 'West', 3)
            ) t (Stat, Region, ID)
            PIVOT
            (   COUNT(ID)
                FOR Region IN ([East], [West], [North], [South])
            ) AS pvt;