使用Rollup从SQL Server中获取mm / dd / yyyy的月份和年度计数值

时间:2016-03-10 23:33:09

标签: sql-server rollup

我有一个数据库表,如下所示,有超过100000条记录:

enter image description here

我正在尝试对此实施汇总查询,以便我可以检索特定项目的记录并按月显示数量。

enter image description here

我有超过100000条记录,有15列。目前,它基于按年和月的迭代选择查询来检索以计算总和。我想使用汇总来加速检索。

1 个答案:

答案 0 :(得分:1)

您只需要进行条件聚合:

DECLARE @fromYear   INT = 2010,
        @toYear     INT = 2014

DECLARE @fromDate   DATE,
        @toDate     DATE

-- Generate date range based on @fromYear and @toYear
SELECT
    @fromDate = DATEADD(YEAR, @fromYear - 1900, 0),
    @toDate   = DATEADD(YEAR, @toYear - 1900 + 1, 0)

SELECT
    YEAR(soldDate), 
    [Jan] = SUM(CASE WHEN MONTH(soldDate) = 1  THEN quantity ELSE 0 END),
    [Feb] = SUM(CASE WHEN MONTH(soldDate) = 2  THEN quantity ELSE 0 END),
    [Mar] = SUM(CASE WHEN MONTH(soldDate) = 3  THEN quantity ELSE 0 END),
    [Apr] = SUM(CASE WHEN MONTH(soldDate) = 4  THEN quantity ELSE 0 END),
    [May] = SUM(CASE WHEN MONTH(soldDate) = 5  THEN quantity ELSE 0 END),
    [Jun] = SUM(CASE WHEN MONTH(soldDate) = 6  THEN quantity ELSE 0 END),
    [Jul] = SUM(CASE WHEN MONTH(soldDate) = 7  THEN quantity ELSE 0 END),
    [Aug] = SUM(CASE WHEN MONTH(soldDate) = 8  THEN quantity ELSE 0 END),
    [Sep] = SUM(CASE WHEN MONTH(soldDate) = 9  THEN quantity ELSE 0 END),
    [Oct] = SUM(CASE WHEN MONTH(soldDate) = 10 THEN quantity ELSE 0 END),
    [Nov] = SUM(CASE WHEN MONTH(soldDate) = 11 THEN quantity ELSE 0 END),
    [Dec] = SUM(CASE WHEN MONTH(soldDate) = 12 THEN quantity ELSE 0 END)
FROM tbl
WHERE
    item = 'basketball'
    AND soldDate >= @fromDate
    AND soldDate < @toDate
GROUP BY YEAR(soldDate)

如果您想要显示所有年份,包括那些包含0件商品的年份,您需要先生成所有这些年份。你可以使用计数表来做到这一点。然后,结果将LEFT JOIN添加到上面的原始查询:

DECLARE @fromYear   INT = 2010,
        @toYear     INT = 2014

DECLARE @fromDate   DATE,
        @toDate     DATE

-- Generate date range based on @fromYear and @toYear
SELECT
    @fromDate = DATEADD(YEAR, @fromYear - 1900, 0),
    @toDate   = DATEADD(YEAR, @toYear - 1900 + 1, 0)

;WITH E1(N) AS(
    SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b),
CteTally(N) AS(
    SELECT TOP(@toYear - @fromYear) 
        ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
    FROM E4
),
CteAgg AS(
    SELECT
        [Yr]  = YEAR(soldDate),
        [Jan] = SUM(CASE WHEN MONTH(soldDate) = 1  THEN quantity ELSE 0 END),
        [Feb] = SUM(CASE WHEN MONTH(soldDate) = 2  THEN quantity ELSE 0 END),
        [Mar] = SUM(CASE WHEN MONTH(soldDate) = 3  THEN quantity ELSE 0 END),
        [Apr] = SUM(CASE WHEN MONTH(soldDate) = 4  THEN quantity ELSE 0 END),
        [May] = SUM(CASE WHEN MONTH(soldDate) = 5  THEN quantity ELSE 0 END),
        [Jun] = SUM(CASE WHEN MONTH(soldDate) = 6  THEN quantity ELSE 0 END),
        [Jul] = SUM(CASE WHEN MONTH(soldDate) = 7  THEN quantity ELSE 0 END),
        [Aug] = SUM(CASE WHEN MONTH(soldDate) = 8  THEN quantity ELSE 0 END),
        [Sep] = SUM(CASE WHEN MONTH(soldDate) = 9  THEN quantity ELSE 0 END),
        [Oct] = SUM(CASE WHEN MONTH(soldDate) = 10 THEN quantity ELSE 0 END),
        [Nov] = SUM(CASE WHEN MONTH(soldDate) = 11 THEN quantity ELSE 0 END),
        [Dec] = SUM(CASE WHEN MONTH(soldDate) = 12 THEN quantity ELSE 0 END)
    FROM tbl t
    WHERE
        item = 'basketball'
        AND soldDate >= @fromDate
        AND soldDate < @toDate
    GROUP BY YEAR(soldDate)
)
SELECT
    [Yr] = (@fromYear + t.N - 1),
    [Jan] = ISNULL([Jan], 0),
    [Feb] = ISNULL([Feb], 0),
    [Mar] = ISNULL([Mar], 0),
    [Apr] = ISNULL([Apr], 0),
    [May] = ISNULL([May], 0),
    [Jun] = ISNULL([Jun], 0),
    [Jul] = ISNULL([Jul], 0),
    [Aug] = ISNULL([Aug], 0),
    [Sep] = ISNULL([Sep], 0),
    [Oct] = ISNULL([Oct], 0),
    [Nov] = ISNULL([Nov], 0),
    [Dec] = ISNULL([Dec], 0)
FROM CteTally t
LEFT JOIN CteAgg a
    ON (@fromYear + t.N - 1) = a.Yr
ORDER BY (@fromYear + t.N - 1)
DROP TABLE tbl

ONLINE DEMO