Изменение суммы вернул NULL в ноль - PullRequest
26 голосов
/ 10 мая 2010

У меня есть хранимая процедура следующим образом:

CREATE PROC [dbo].[Incidents]
(@SiteName varchar(200))

AS

SELECT

(  
    SELECT SUM(i.Logged)  
    FROM tbl_Sites s  
    INNER JOIN tbl_Incidents i  
    ON s.Location = i.Location  
    WHERE s.Sites = @SiteName AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)  
    GROUP BY s.Sites  
)  AS LoggedIncidents

'tbl_Sites contains a list of reported on sites.
'tbl_Incidents containts a generated list of total incidents by site/date (monthly)
'If a site doesnt have any incidents that month it wont be listed.

Проблема, с которой я столкнулся, заключается в том, что в этом месяце на сайте не было инцидентов, и поэтому я получаю значение NULL, возвращаемое для этого сайта, когда я запускаю этот sproc, но мне нужно вернуть ноль / 0 для использования в рамках диаграммы в SSRS.

Я пробовал использовать coalesce и безрезультатно.

    SELECT COALESCE(SUM(c.Logged,0))
    SELECT SUM(ISNULL(c.Logged,0))

Есть ли способ правильно отформатировать это?

Приветствия

Lee

Ответы [ 6 ]

46 голосов
/ 10 мая 2010

Поместите это снаружи:

SELECT COALESCE(

(  
    SELECT SUM(i.Logged)  
    FROM tbl_Sites s  
    INNER JOIN tbl_Incidents i  
    ON s.Location = i.Location  
    WHERE s.Sites = @SiteName AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)  
    GROUP BY s.Sites  
), 0)  AS LoggedIncidents

Если вы возвращаете несколько строк, измените INNER JOIN на LEFT JOIN

SELECT COALESCE(SUM(i.Logged),0)
FROM tbl_Sites s  
LEFT JOIN tbl_Incidents i  
ON s.Location = i.Location  
WHERE s.Sites = @SiteName AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)  
GROUP BY s.Sites  

Кстати, не помещайте никакие функции или выражения в агрегатные функции, если это не гарантируется, например, не помещайте ISNULL, COALESCE в SUM, используя функцию / выражение внутри агрегации, которая снижает производительность, запрос будет выполнен с помощью сканирования таблицы

23 голосов
/ 10 мая 2010

Вам нужно будет использовать ISNULL вот так -

ISNULL(SUM(c.Logged), 0)      

Или, как сказал Майкл, вы можете использовать левое внешнее соединение.

7 голосов
/ 01 октября 2016

Я столкнулся с этой проблемой в Oracle. Oracle не имеет функции ISNULL(). Однако мы можем использовать функцию NVL() для достижения того же результата:

NVL(SUM(c.Logged), 0)
2 голосов
/ 10 мая 2010

Самый простой и удобный для чтения способ, который я нашел для достижения этой цели, это:

CREATE PROC [dbo].[Incidents]
(@SiteName varchar(200))

AS

    SELECT SUM(COALESCE(i.Logged, 0)) AS LoggedIncidents
    FROM tbl_Sites s  
    INNER JOIN tbl_Incidents i  
    ON s.Location = i.Location  
    WHERE s.Sites = @SiteName 
          AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)  
    GROUP BY s.Sites  
1 голос
/ 13 августа 2010

Просто столкнулся с этой проблемой, решение Киртана у меня хорошо работало, но синтаксис был немного не в порядке. Я сделал это так:

ISNULL(SUM(c.Logged), 0)

Пост помог мне решить мою проблему, так что спасибо всем.

1 голос
/ 10 мая 2010

Вы можете поместить SELECT в другой SELECT следующим образом:

 CREATE PROC [dbo].[Incidents]
(@SiteName varchar(200))

AS

SELECT COALESCE(TotalIncidents  ,0)
FROM (
  SELECT
  (  
    SELECT SUM(i.Logged) as TotalIncidents  
    FROM tbl_Sites s  
    INNER JOIN tbl_Incidents i  
    ON s.Location = i.Location  
    WHERE s.Sites = @SiteName AND i.[month] = DATEADD(mm, DATEDIFF(mm, 0, GetDate()) -1,0)  
    GROUP BY s.Sites  
  )  AS LoggedIncidents
)
...