如何在给定的日期范围内按周计算一年

时间:2015-04-17 20:16:39

标签: sql-server

我有一个表,包括创建日期,创建项目的ID以及其他不重要的信息。我想要做的是编写一个查询,该查询总结了在给定日期范围内按周创建的项目。所以如果我有这张桌子:

ID   creationdate
--   ------------
 1   1/1/2015
 2   1/2/2015
 3   1/3/2015
 4   1/3/2015
 5   1/3/2015
 6   1/5/2015
 7   1/6/2015

如果我要查询2014年12月29日至2015年1月11日的日期范围,我希望看到以下结果:

weekof       count
------       -----
12/29/2014     5
 1/05/2015     7

有没有办法实现这个目标?

1 个答案:

答案 0 :(得分:1)

计算表上累积值的一种方法是创建自联接并使用> =比较运算符连接已连接的字段。

从您的问题看来,您的一周从星期一开始。因此,您还需要计算表中每行的前一个星期一。在我的解决方案中,我使用DATENAME计算了当天的名称,然后从创建日期中减去创建日期过去一周的天数。

最后,我使用FORMAT函数格式化了日期。

CREATE TABLE [dbo].[DateTest]  ---Create Test Table DateTest
(
    [ID] [int] NULL,
    [CreationDate] [datetime] NULL
)
GO

---Insert Values
INSERT INTO
    DateTest
VALUES
    ('1','1/1/2015'),
    ('2','1/2/2015'),
    ('3','1/3/2015'),
    ('4','1/3/2015'),
    ('5','1/3/2015'),
    ('6','1/5/2015'),
    ('7','1/6/2015')
GO

---Perform the calculation
SELECT
    FORMAT(t1.StartOfWeek, 'd', 'en-US') as StartOfWeek, ----Render date as mm/dd/yyyy
    SUM(t2.CountForWeek) as CumulativeRecordCount
FROM
    (
    SELECT
        (CASE --Determine the most recent preceding Monday, because Monday is defined as the beginning of the week
            WHEN DATENAME(dw,CreationDate) = 'Sunday' THEN CreationDate-6
            WHEN DATENAME(dw,CreationDate) = 'Saturday' THEN CreationDate-5
            WHEN DATENAME(dw,CreationDate) = 'Friday' THEN CreationDate-4
            WHEN DATENAME(dw,CreationDate) = 'Thursday' THEN CreationDate-3
            WHEN DATENAME(dw,CreationDate) = 'Wednesday' THEN CreationDate-2
            WHEN DATENAME(dw,CreationDate) = 'Tuesday' THEN CreationDate-1
            ELSE CreationDate
        END) AS StartOfWeek,
        COUNT(id) AS CountForWeek
    FROM
        DateTest
    GROUP BY
        (CASE --Determine the most recent preceding Monday, because Monday is defined as the beginning of the week
            WHEN DATENAME(dw,CreationDate) = 'Sunday' THEN CreationDate-6
            WHEN DATENAME(dw,CreationDate) = 'Saturday' THEN CreationDate-5
            WHEN DATENAME(dw,CreationDate) = 'Friday' THEN CreationDate-4
            WHEN DATENAME(dw,CreationDate) = 'Thursday' THEN CreationDate-3
            WHEN DATENAME(dw,CreationDate) = 'Wednesday' THEN CreationDate-2
            WHEN DATENAME(dw,CreationDate) = 'Tuesday' THEN CreationDate-1
            ELSE CreationDate
        END)
    ) AS t1
INNER JOIN --Self Join Table
    (
    SELECT
        (CASE --Determine the most recent preceding Monday, because Monday is defined as the beginning of the week
            WHEN DATENAME(dw,CreationDate) = 'Sunday' THEN CreationDate-6
            WHEN DATENAME(dw,CreationDate) = 'Saturday' THEN CreationDate-5
            WHEN DATENAME(dw,CreationDate) = 'Friday' THEN CreationDate-4
            WHEN DATENAME(dw,CreationDate) = 'Thursday' THEN CreationDate-3
            WHEN DATENAME(dw,CreationDate) = 'Wednesday' THEN CreationDate-2
            WHEN DATENAME(dw,CreationDate) = 'Tuesday' THEN CreationDate-1
            ELSE CreationDate
        END) AS StartOfWeek,
        COUNT(id) AS CountForWeek
    FROM
        DateTest
    GROUP BY
            (CASE --Determine the most recent preceding Monday, because Monday is defined as the beginning of the week
            WHEN DATENAME(dw,CreationDate) = 'Sunday' THEN CreationDate-6
            WHEN DATENAME(dw,CreationDate) = 'Saturday' THEN CreationDate-5
            WHEN DATENAME(dw,CreationDate) = 'Friday' THEN CreationDate-4
            WHEN DATENAME(dw,CreationDate) = 'Thursday' THEN CreationDate-3
            WHEN DATENAME(dw,CreationDate) = 'Wednesday' THEN CreationDate-2
            WHEN DATENAME(dw,CreationDate) = 'Tuesday' THEN CreationDate-1
            ELSE CreationDate
        END)
    ) AS t2
    ON
    t1.StartOfWeek >= t2.StartOfWeek --- join t2.startofweek to all t1.startofweek dates greater than or equal to t2.startofweek
GROUP BY
    t1.StartOfWeek

输出

StartOfWeek   CumulativeRecordCount
------------- ---------------------
12/29/2014            5
1/5/2015              7