处理ssrs图表的sql查询表达式中不存在的值

时间:2012-03-13 20:44:30

标签: sql sql-server ssrs-2008 bids

我在ssrs折线图中使用以下查询。它根据每个订单日期计算每月记录的订单数量。

我的问题是,当一个月没有订单时,不是说零或空,而是一起删除该月的行。我更愿意把它算作零,但是null也可以。

基本上,我想总是有12行,无论它们是否包含信息。

我该如何解决这个问题?有可以使用的表达式吗?或者我错过了一些完全明显的东西?

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 Ord
JOIN Prod ON Ord.Prod_ID = Prod.ID
JOIN ProdType ON Prod.ProdType_ID = ProdType.ID
JOIN Grouping ON Ord.Grouping_ID = Grouping.ID
JOIN Worker ON Grouping.Worker_ID = Worker.ID

WHERE @Year = YEAR(Ord.OrdDate)
AND (@ProdType_ID IS NULL OR @ProdType_ID = ProdType.ID)

GROUP BY MONTH(Ord.OrdDate)

6 个答案:

答案 0 :(得分:3)

如上所述,你需要一个外连接和某种日历表。这是未经测试的,但我认为对您有用:

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)

答案 1 :(得分:0)

您需要一个包含月份的表才能使其工作(或者您可以使用存储过程或可能使用公用表表达式。)

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

确保你得到:

Month, Count
1, 1
2, 1
3, 2
4, NULL
etc

答案 2 :(得分:0)

;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;

答案 3 :(得分:0)

通过删除where子句并过滤count聚合来实现它。

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)

答案 4 :(得分:0)

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

只需将您的查询复制并粘贴到占位符即可。 您将始终只获得12行。而且也不需要创建任何表格。

答案 5 :(得分:-1)

SQL构造“内部联接”很好地定义了这种行为。 使用左连接(或右连接,取决于哪一个是正确的一面)在不满足连接条件时检索空值,如下所示(未测试)

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)

注意 - 我添加了额外的where子句条件来检查orddate上的year函数,因为它可以为null

谷歌加入SQL,我相信你会发现比这更多的质量信息

希望这有帮助