web-dev-qa-db-fra.com

La modification d'un SUM a renvoyé NULL à zéro

J'ai une procédure stockée comme suit:

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 contains a generated list of total incidents by site/date (monthly)
'If a site doesn't have any incidents that month it wont be listed.

Le problème que j'ai est qu'un site n'a aucun incident ce mois-ci et en tant que tel, j'ai reçu une valeur NULL pour ce site lorsque j'exécute ce proc, mais j'ai besoin d'un zéro/0 retourné pour être utilisé dans un graphique en SSRS.

J'ai essayé d'utiliser coalesce et isnull en vain.

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

Existe-t-il un moyen d'obtenir ce format correctement?

À votre santé,

Lee

28
Icementhols

Mettez-le à l'extérieur:

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

Si vous retournez plusieurs lignes, remplacez INNER JOIN par 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  

Soit dit en passant, ne placez aucune fonction ou expression dans les fonctions d'agrégation si cela n'est pas garanti, par ex. ne mettez pas ISNULL, COALESCE à l'intérieur de SUM, l'utilisation de la fonction/expression à l'intérieur de l'agrégation paralyse les performances, la requête sera exécutée avec l'analyse de la table

49
Michael Buen

Vous devrez utiliser ISNULL comme ceci -

ISNULL(SUM(c.Logged), 0)      

Ou, comme Michael l'a dit, vous pouvez utiliser une jointure externe gauche.

25
Kirtan

J'ai rencontré ce problème dans Oracle. Oracle n'a pas de fonction ISNULL(). Cependant, nous pouvons utiliser la fonction NVL() pour obtenir le même résultat:

NVL(SUM(c.Logged), 0)
8
Guangtong Shen

Le moyen le plus simple et le plus lisible que j'ai trouvé pour y parvenir est de:

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  
2
Jeremiah Peschka

Vous pouvez envelopper le SELECT dans un autre SELECT comme ceci:

 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
)
1

Je viens de rencontrer ce problème, la solution de Kirtan a bien fonctionné pour moi, mais la syntaxe était un peu décalée. J'ai aimé ça:

ISNULL(SUM(c.Logged), 0)

La poste m'a cependant aidé à résoudre mon problème, donc merci à tous.

1
jaywon