简体   繁体   中英

How to show NULL instead of 0 when using sum aggregate / pivoting

Consider this 24-hour summary. The problem is that I'm getting 0s returned for hours where values haven't been inserted yet. I believe this is due to the SUM() function call.

SELECT
    section,
    [21], [22], [23], [0], [1], [2], [3], [4], [5], [6], [7], [8],
    [21] + [22] + [23] + [0] + [1] + [2] + [3] + [4] + [5] + [6] + [7] + [8] as s1_total
    -- shift 2 fields are ommitted for brievity
FROM (
    SELECT 
        section,
        -- hours from 21:00 (1st shift) to 20:00 (2nd shift)
        SUM(CASE WHEN prTime = '21:00:00' THEN Amount ELSE 0 END) AS [21],
        SUM(CASE WHEN prTime = '22:00:00' THEN Amount ELSE 0 END) AS [22],
        SUM(CASE WHEN prTime = '23:00:00' THEN Amount ELSE 0 END) AS [23],
        SUM(CASE WHEN prTime = '00:00:00' THEN Amount ELSE 0 END) AS [0],
        SUM(CASE WHEN prTime = '01:00:00' THEN Amount ELSE 0 END) AS [1],
        SUM(CASE WHEN prTime = '02:00:00' THEN Amount ELSE 0 END) AS [2],           
        -- ... similar cases are omitted for brieviety
        SUM(CASE WHEN prTime = '20:00:00' THEN Amount ELSE 0 END) AS [20]
    FROM (
        SELECT prTime, prDate, section01 AS Amount, 'section 1' as [Section] FROM SectionsHourlyValues
        UNION
        SELECT prTime, prDate, section02 AS Amount, 'section 2' as [Section] FROM SectionsHourlyValues
        UNION
        SELECT prTime, prDate, section03 AS Amount, 'section 3' as [Section] FROM SectionsHourlyValues
    ) AS U
    WHERE 
        (prDate = CONVERT(DATE, DATEADD(HOUR, -4, CONVERT(DATETIME2(7), @dt, 104))) and prTime > '20:00:00') or 
        (prDate = CONVERT(DATE, @dt, 104) and prTime <= '20:00:00')
    GROUP BY section
) t;

For example, running the query

DECLARE @dt varchar(10) = 'certain_date';
SELECT * from [dbo].[SectionsHourlyValues] WHERE
    (prDate = CONVERT(DATE, DATEADD(HOUR, -4, CONVERT(DATETIME2(7), @dt, 104))) and prTime > '20:00:00') or 
    (prDate = CONVERT(DATE, @dt, 104) and prTime <= '20:00:00');

wouldn't return us the data for say 09:00:00 / section1 whereas the summary would show us 0 .

Then I want to show NULL (for not yet inserted records) instead of 0 . How do I do that?

Use NULLIF

ex

NULLIF(SUM(CASE WHEN prTime = '21:00:00' THEN Amount ELSE 0 END),0)

or simply do not use ELSE

SUM(CASE WHEN prTime = '21:00:00' THEN Amount END)

在条件聚合中用NULL替换0怎么样?

SUM(CASE WHEN etc... ELSE NULL END)

You're getting 0 values not due to the SUM function for values not yet inserted (that would be NULL and would ignored by the SUM function), but because the ELSE of your CASE statement returns 0:

SUM(CASE WHEN prTime = '21:00:00' THEN Amount ELSE 0 END) AS [21]

To solve your problem, you can use NULLIF that is rather similar to CASE :

NULLIF(MyExpressionThatCouldReturn0, 0)

That in your case would be:

NULLIF(SUM(CASE WHEN prTime = '01:00:00' THEN Amount ELSE 0 END),0)

Otherwise, as said before, do not use ELSE in the CASE statement, used as parameter of your SUM:

SUM(CASE WHEN prTime = '21:00:00' THEN Amount END)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM