按月比较产品销售额的 SQL 查询

Jon*_*esø 5 sql sql-server reporting sql-server-2005

我有一个每月状态数据库视图,我需要基于它来构建报告。视图中的数据如下所示:

Category | Revenue  |  Yearh  |  Month
Bikes      10 000      2008        1
Bikes      12 000      2008        2
Bikes      12 000      2008        3
Bikes      15 000      2008        1
Bikes      11 000      2007        2
Bikes      11 500      2007        3
Bikes      15 400      2007        4
Run Code Online (Sandbox Code Playgroud)


......等等

该视图具有产品类别、收入、年份和月份。我想创建一个比较 2007 年和 2008 年的报告,在没有销售的月份显示 0。所以报告应该是这样的:

Category  |  Month  |  Rev. This Year  |  Rev. Last Year
Bikes          1          10 000               0
Bikes          2          12 000               11 000
Bikes          3          12 000               11 500
Bikes          4          0                    15 400
Run Code Online (Sandbox Code Playgroud)


要注意的关键是第 1 个月只有 2008 年的销售额,因此 2007 年为 0。此外,第 4 个月只有 2008 年没有销售额,因此为 0,而它在 2007 年有销售额并且仍然出现。

此外,该报告实际上是针对财政年度的 - 因此,如果 2007 年或 2008 年的第 5 个月没有销售,我希望在两个列中都有 0 的空列。

我得到的查询看起来像这样:

SELECT 
    SP1.Program,
    SP1.Year,
    SP1.Month,
    SP1.TotalRevenue,
    IsNull(SP2.TotalRevenue, 0) AS LastYearTotalRevenue

FROM PVMonthlyStatusReport AS SP1 
     LEFT OUTER JOIN PVMonthlyStatusReport AS SP2 ON 
                SP1.Program = SP2.Program AND 
                SP2.Year = SP1.Year - 1 AND 
                SP1.Month = SP2.Month
WHERE 
    SP1.Program = 'Bikes' AND
    SP1.Category = @Category AND 
    (SP1.Year >= @FinancialYear AND SP1.Year <= @FinancialYear + 1) AND
    ((SP1.Year = @FinancialYear AND SP1.Month > 6) OR 
     (SP1.Year = @FinancialYear + 1 AND SP1.Month <= 6))

ORDER BY SP1.Year, SP1.Month
Run Code Online (Sandbox Code Playgroud)

这个查询的问题在于它不会返回我上面示例数据中的第四行,因为我们在 2008 年没有任何销售额,但我们实际上在 2007 年有。

这可能是一个常见的查询/问题,但是我的 SQL 在做了这么长时间的前端开发后生锈了。任何帮助是极大的赞赏!

哦,顺便说一句,我正在使用 SQL 2005 进行此查询,因此如果有任何有用的新功能可能会帮助我知道,请告诉我。

jas*_*ldo 5

Case 语句是我最好的 sql 朋友。您还需要一个时间表来在两个月内生成 0 转。

假设基于下表的可用性:

销售: 类别 | 收入 | 年 | 月

tm: 年 | 月(填充报告所需的所有日期)

没有空行的示例 1:

select
    Category
    ,month
    ,SUM(CASE WHEN YEAR = 2008 THEN Revenue ELSE 0 END) this_year
    ,SUM(CASE WHEN YEAR = 2007 THEN Revenue ELSE 0 END) last_year

from
    sales

where
    year in (2008,2007)

group by
    Category
    ,month
Run Code Online (Sandbox Code Playgroud)

退货:

Category  |  Month  |  Rev. This Year  |  Rev. Last Year
Bikes          1          10 000               0
Bikes          2          12 000               11 000
Bikes          3          12 000               11 500
Bikes          4          0                    15 400
Run Code Online (Sandbox Code Playgroud)

带有空行的示例 2:我将使用子查询(但其他人可能不会)并将为每个产品和年月组合返回一个空行。

select
    fill.Category
    ,fill.month
    ,SUM(CASE WHEN YEAR = 2008 THEN Revenue ELSE 0 END) this_year
    ,SUM(CASE WHEN YEAR = 2007 THEN Revenue ELSE 0 END) last_year

from
    sales
    Right join (select distinct  --try out left, right and cross joins to test results.
                   product
                   ,year
                   ,month
               from
                  sales --this ideally would be from a products table
                  cross join tm
               where
                    year in (2008,2007)) fill


where
    fill.year in (2008,2007)

group by
    fill.Category
    ,fill.month
Run Code Online (Sandbox Code Playgroud)

退货:

Category  |  Month  |  Rev. This Year  |  Rev. Last Year
Bikes          1          10 000               0
Bikes          2          12 000               11 000
Bikes          3          12 000               11 500
Bikes          4          0                    15 400
Bikes          5          0                    0
Bikes          6          0                    0
Bikes          7          0                    0
Bikes          8          0                    0
Run Code Online (Sandbox Code Playgroud)

请注意,大多数报告工具都会执行此交叉表或矩阵功能,现在我认为 SQL Server 2005 具有可以执行此操作的数据透视语法。

这里有一些额外的资源。案例 http://www.4guysfromrolla.com/webtech/102704-1.shtml SQL SERVER 2005 PIVOT http://msdn.microsoft.com/en-us/library/ms177410.aspx