Handling non existent values in sql query expression for ssrs chart

后端 未结 6 1839
野性不改
野性不改 2020-12-20 10:49

I am using the following query in an ssrs line chart. It counts how many orders are recorded each month based on each order date.

My problem is that when a month has

相关标签:
6条回答
  • 2020-12-20 11:01
    select a.mon,b.* from
    (
    select 1 as mon union select 2 as mon union select 3 as mon union select 4 as mon union 
    select 5 as mon union select 6 as mon union select 7 as mon union select 8 as mon union 
    select 9 as mon union select 10 as mon union select 11 as mon union  select 12 as mon 
    ) a
    left outer join
    (
       your existing query here
    ) b
    on a.mon=b.MONTH(OrdDate)
    go
    

    Just copy and paste your query in the place holder and go. You will always get 12 rows only. And there is no need to create any tables too.

    0 讨论(0)
  • 2020-12-20 11:14
    ;WITH m(m) AS ( SELECT TOP 12 ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.objects )
    SELECT [MONTH] = m.m,
      Worker1 = COUNT(CASE WHEN COALESCE(@Worker_ID1, w.ID) = w.ID THEN 1 END),
      Worker2 = COUNT(CASE WHEN COALESCE(@Worker_ID2, w.ID) = w.ID THEN 1 END),
      Worker3 = COUNT(CASE WHEN COALESCE(@Worker_ID3, w.ID) = w.ID THEN 1 END),
      Worker4 = COUNT(CASE WHEN COALESCE(@Worker_ID4, w.ID) = w.ID THEN 1 END),
      Worker5 = COUNT(CASE WHEN COALESCE(@Worker_ID5, w.ID) = w.ID THEN 1 END)
    FROM m
    LEFT OUTER JOIN dbo.Ord AS o
    ON o.OrdDate >= DATEADD(MONTH, m.m-1, RTRIM(@Year)+'0101')
    AND o.OrdDate < DATEADD(MONTH, m.m, RTRIM(@Year+'0101')
    INNER JOIN dbo.Prod     AS p  ON o.Prod_ID     = p.ID
    INNER JOIN dbo.ProdType AS pt ON p.ProdType_ID = pt.ID
    INNER JOIN dbo.Grouping AS g  ON o.Grouping_ID = g.ID
    INNER JOIN dbo.Worker   AS w  ON g.Worker_ID   = w.ID
    WHERE (@DrugType_ID IS NULL OR pt.ID = @ProdType_ID)
    GROUP BY m.m
    ORDER BY m.m;
    
    0 讨论(0)
  • 2020-12-20 11:20

    You need a table containing months in order to make this work (or you can use a stored procedure or probably common table expression).

    SELECT Months.Month, COUNT(Orders.OrderID)
    FROM
     Months
    LEFT OUTER JOIN
     Orders
    ON
     MONTH(Orders.OrderDate) = Months.Month
    

    Would ensure you got:

    Month, Count
    1, 1
    2, 1
    3, 2
    4, NULL
    etc
    
    0 讨论(0)
  • 2020-12-20 11:24

    that behavior is well defined by SQL construct "Inner join". use left join (or right join, depending on which is correct side) to retrieve null values when the join condition is not satisfied as below (not tested)

    SELECT
    MONTH(Ord.OrdDate) AS 'MONTH',
    COUNT(CASE WHEN @Worker_ID1 IS NULL OR @Worker_ID1 = Worker.ID THEN 1 END) AS 'Worker1',
    COUNT(CASE WHEN @Worker_ID2 IS NULL OR @Worker_ID2 = Worker.ID THEN 1 END) AS 'Worker2',
    COUNT(CASE WHEN @Worker_ID3 IS NULL OR @Worker_ID3 = Worker.ID THEN 1 END) AS 'Worker3',
    COUNT(CASE WHEN @Worker_ID4 IS NULL OR @Worker_ID4 = Worker.ID THEN 1 END) AS 'Worker4',
    COUNT(CASE WHEN @Worker_ID5 IS NULL OR @Worker_ID5 = Worker.ID THEN 1 END) AS 'Worker5'
    
    FROM Prod 
    LEFT JOIN ORD ON Ord.Prod_ID = Prod.ID
    JOIN ProdType ON Prod.ProdType_ID = ProdType.ID
    JOIN Grouping ON Ord.Grouping_ID = Groupord.ID
    JOIN Worker ON Grouping.Worker_ID = Worker.ID
    
    WHERE ((Ord.OrdDate is not null and @Year = YEAR(Ord.OrdDate)) or ORD.prod_id is null)
    AND (@ProdType_ID IS NULL OR @ProdType_ID = ProdType.ID)
    
    GROUP BY MONTH(Ord.OrdDate)
    

    Note - i added additional where clause conditions to check on the year function on orddate as this can be null

    google for joins SQL and am sure you will find much more quality information than this

    Hope this helps

    0 讨论(0)
  • 2020-12-20 11:25

    Got it working by removing the where clause and filtering in the count aggregate.

    SELECT
    MONTH(Ord.OrdDate) AS 'MONTH',
    COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) AND Worker.ID = @Worker_ID1 AND @ProdType_ID = ProdType.ID THEN 1 END) AS 'Worker1',
    COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) AND Worker.ID = @Worker_ID2 AND @ProdType_ID = ProdType.ID THEN 1 END) AS 'Worker2',
    COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) AND Worker.ID = @Worker_ID3 AND @ProdType_ID = ProdType.ID THEN 1 END) AS 'Worker3',
    COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) AND Worker.ID = @Worker_ID4 AND @ProdType_ID = ProdType.ID THEN 1 END) AS 'Worker4',
    COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) AND Worker.ID = @Worker_ID5 AND @ProdType_ID = ProdType.ID THEN 1 END) AS 'Worker5'
    
    FROM Ord
    JOIN Grouping ON Ord.Grouping_ID = Grouping.ID
    JOIN Worker ON Grouping.Worker_ID = Worker.ID
    JOIN Prod ON Ord.Prod_ID = Prod.ID
    JOIN ProdType ON Prod.ProdType_ID = ProdType.ID 
    
    GROUP BY MONTH(Ord.OrdDate)
    
    0 讨论(0)
  • 2020-12-20 11:26

    As the above answers mentioned, you will need an outer join and some kind of calendar table. This is untested, but I think will work for you:

    with dateCTE as
    (
         select cast('2012-01-01' as datetime) dateValue -- start date
         union all
         select DateAdd(mm, 1, dateValue)
         from    dateCTE   
         where   dateValue < '2012-12-30' -- end date
     )
    SELECT
    MONTH(dateCTE.dateValue) AS 'MONTH',
    COUNT(CASE WHEN @Worker_ID1 IS NULL OR @Worker_ID1 = Worker.ID THEN 1 END) AS 'Worker1',
    COUNT(CASE WHEN @Worker_ID2 IS NULL OR @Worker_ID2 = Worker.ID THEN 1 END) AS 'Worker2',
    COUNT(CASE WHEN @Worker_ID3 IS NULL OR @Worker_ID3 = Worker.ID THEN 1 END) AS 'Worker3',
    COUNT(CASE WHEN @Worker_ID4 IS NULL OR @Worker_ID4 = Worker.ID THEN 1 END) AS 'Worker4',
    COUNT(CASE WHEN @Worker_ID5 IS NULL OR @Worker_ID5 = Worker.ID THEN 1 END) AS 'Worker5'
    
    FROM dateCTE
    LEFT JOIN Ord on MONTH(dateCTE.datevalue) = MONTH(Ord.OrdDate)
    JOIN Prod ON Ord.Prod_ID = Prod.ID
    JOIN ProdType ON Prod.ProdType_ID = ProdType.ID
    JOIN Groupord ON Ord.Groupord_ID = Groupord.ID
    JOIN Worker ON Groupord.Worker_ID = Worker.ID
    
    WHERE (@Year = YEAR(Ord.OrdDate) or ORD.prod_id is null)
    AND (@DrugType_ID IS NULL OR @ProdType_ID = ProdType.ID)
    
    GROUP BY MONTH(dateCTE.dateValue)
    OPTION  (MAXRECURSION 0)
    
    0 讨论(0)
提交回复
热议问题