在ssrs图表的sql查询中处理不存在的分组值

时间:2012-04-04 17:03:07

标签: sql sql-server tsql ssrs-2008

我在ssrs报告中使用以下查询。

Declare @Year int = 2012
Declare @ProdType_ID int = 1

SELECT
MONTH(Ord.OrdDate) AS 'MONTH',
COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) THEN 1 END) as Order1,
COUNT(CASE WHEN @Year-1 = YEAR(Ord.OrdDate) THEN 1 END) as 'Order2'
FROM
(
select 1 as number
union
select 2
union
select 3
union
select 4
union
select 5
union
select 6
union
select 7
union
select 8
union
select 9
union
select 10
union
select 11
union
select 12
) as months

JOIN Ord on Number = Month(Ord.OrdDate)
JOIN Prod ON Ord.Prod_ID = Prod.ID
JOIN ProdType ON Prod.ProdType_ID = ProdType.ID 
WHERE @ProdType_ID = ProdType.ID
GROUP BY months.number, Month(Ord.OrdDate)

这会返回一个包含正确分组的表格,但未显示尚未记录或未记录的月份这一事实除外。我希望每个月都能显示,即使它尚未通过,我希望他们的订单价值为零。

我是否可以通过某种方式在FROM子句中放置数组或类似内容? 感谢。

3 个答案:

答案 0 :(得分:1)

我想你可能想要使用OUTER JOIN。 使用 left 外部联接,查询将返回FROM子句中“左表”中具有满足任何WHERE条件的行的所有行。其他表中的列值将为NULL。因此,如果需要特殊处理NULL,您可能需要在select语句中使用的列值周围添加ISNULL函数。

此MSDN文章Using Outer Joins包含更完整的信息。

我使用左外连接重写了你的查询。你可能需要对case语句做一些额外的工作,但可能不需要 - 如果参数值为NULL,YEAR函数将返回NULL,我认为逻辑可以成立。

Declare @Year int = 2012
Declare @ProdType_ID int = 1

SELECT
MONTH(Ord.OrdDate) AS 'MONTH',
COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) THEN 1 END) as Order1,
COUNT(CASE WHEN @Year-1 = YEAR(Ord.OrdDate) THEN 1 END) as 'Order2'
FROM
(
select 1 as number
union
select 2
union
select 3
union
select 4
union
select 5
union
select 6
union
select 7
union
select 8
union
select 9
union
select 10
union
select 11
union
select 12
) as months

LEFT OUTER JOIN Ord on Number = Month(Ord.OrdDate)
LEFT OUTER JOIN Prod ON Ord.Prod_ID = Prod.ID
LEFT OUTER JOIN ProdType ON Prod.ProdType_ID = ProdType.ID 
WHERE @ProdType_ID = ProdType.ID
GROUP BY months.number, Month(Ord.OrdDate)

答案 1 :(得分:1)

在删除WHERE子句并在count聚合中执行所有过滤后,它才起作用。

SELECT
MONTH(Ord.OrdDate) AS 'Month',
COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) and @ProdType_ID = ProdType.ID THEN 1 END) AS Order1,
COUNT(CASE WHEN @Year-1 = YEAR(Ord.OrdDate) and @ProdType_ID = ProdType.ID THEN 1 END) AS Order2

FROM
(
SELECT 1 AS Number 
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6
UNION
SELECT 7
UNION
SELECT 8
UNION
SELECT 9
UNION
SELECT 10
UNION
SELECT 11
UNION
SELECT 12
) AS Months

LEFT OUTER JOIN Ord ON Number = MONTH(Ord.OrdDate)
LEFT OUTER JOIN Prod ON Ord.Prod_ID = Prod.ID
LEFT OUTER JOIN ProdType ON Prod.ProdType_ID = ProdType.ID

GROUP BY Months.Number, MONTH(Ord.OrdDate)

答案 2 :(得分:0)

如果还使用LEFT JOIN。但我建议使用Tally表来获取月份。这将适用于sql server 2005 +:

Declare @Year int = 2012
Declare @ProdType_ID int = 1

;WITH Months ( Number ) AS 
(
        SELECT 1 UNION ALL
        SELECT 1 + Number FROM Months WHERE Number < 12 
)
SELECT
MONTH(Ord.OrdDate) AS 'MONTH',
COUNT(CASE WHEN @Year = YEAR(Ord.OrdDate) THEN 1 END) as Order1,
COUNT(CASE WHEN @Year-1 = YEAR(Ord.OrdDate) THEN 1 END) as 'Order2'
FROM
    Months
LEFT JOIN Ord on Number = Month(Ord.OrdDate)
LEFT JOIN Prod ON Ord.Prod_ID = Prod.ID
LEFT JOIN ProdType ON Prod.ProdType_ID = ProdType.ID 
WHERE @ProdType_ID = ProdType.ID
GROUP BY months.number, Month(Ord.OrdDate)