【问题标题】:Get all start date end date and week number from the year in SQL Server从 SQL Server 中获取一年中的所有开始日期结束日期和周数
【发布时间】:2016-12-30 16:51:30
【问题描述】:

我想从 2016 年 1 月 1 日开始创建开始日期、结束日期和周数。一周的第一天是星期五。这是我想要的下面的示例。

设置一周的第一天是星期五

Start Date  EndDate WeekNumber
1/1/2016    7/1/2016    1
8/1/2016    14/1/2016   2
15/1/2016   21/1/2016   3
…..     
……      
…..     
30/12/2016  5/1/2017    53
6/1/2017    12/1/2017   1
13/1/2017   19/1/2017   2
20/1/2017   26/1/2017   3
…       
….      
…       

请给我任何想法。

我可以在周五的第一天这样

SET DATEFIRST 5
SELECT  DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE)) [WeekStart],
        DATEADD(DAY, 7 - DATEPART(WEEKDAY, GETDATE()), CAST(GETDATE() AS DATE)) [WeekEnd]

通过这种方式获取周数

SELECT { fn WEEK( '2016-01-01') }

【问题讨论】:

  • 一周中的第一天是星期五还是不是星期五并不重要。
  • @SiyavashHamdi,我如何生成这张 2016 年和 2017 年的表格
  • @Shohel,试试答案。
  • @Valkyriee:使用图 db[ms] 解决此类问题/请求有多容易?
  • @Valkyriee,如何使用图 db[ms] 轻松解决此类问题/请求?

标签: c# sql-server sql-server-2012


【解决方案1】:

它在@StartDate 和@StartDate + @NumYears 之间生成一系列的所有周:

您可以更改开始和结束日期,但请注意 MAXRECURSION。

CREATE FUNCTION fnWeek(@StartDate DATETIME)
RETURNS @Weeks TABLE (StartWeekDate DATETIME, EndWeekDate DATETIME, WeekOfYear int)
AS
BEGIN
    DECLARE @NumYears int = 2;

    ;WITH genDates  
    AS (
        SELECT @StartDate AS mdate
        UNION ALL
        SELECT DATEADD(week, 1, mdate) FROM genDates WHERE DATEADD(week, 1, mdate) < DATEADD(year, @NumYears, @StartDate)
    )
    INSERT INTO @Weeks
    SELECT mdate AS StartDate, DATEADD(day,6,mdate) AS EndDate, DATEPART(week, mdate) AS WeekOfYear
    FROM genDates OPTION (MAXRECURSION 0);

    RETURN;
END
GO 

select * from fnWeek('2016-01-01');

或者@NumYears可以作为参数添加:

CREATE FUNCTION fnWeek(@StartDate DATETIME, @NumYears int)
RETURNS @Weeks TABLE (StartWeekDate DATETIME, EndWeekDate DATETIME, WeekOfYear int)
AS
BEGIN

    ;WITH genDates  
    AS (
        SELECT @StartDate AS mdate
        UNION ALL
        SELECT DATEADD(week, 1, mdate) FROM genDates WHERE DATEADD(week, 1, mdate) < DATEADD(year, @NumYears, @StartDate)
    )
    INSERT INTO @Weeks
    SELECT mdate AS StartDate, DATEADD(day,6,mdate) AS EndDate, DATEPART(week, mdate) AS WeekOfYear
    FROM genDates 
    OPTION (MAXRECURSION 0);

    RETURN;
END
GO 

select * from fnWeek('2016-01-01', 2);


+---------------------+---------------------+------+
|    StarWeektDate    |     EndWeekDate     | Week |
+---------------------+---------------------+------+
| 01.01.2016 00:00:00 | 07.01.2016 00:00:00 |   1  |
+---------------------+---------------------+------+
| 08.01.2016 00:00:00 | 14.01.2016 00:00:00 |   2  |
+---------------------+---------------------+------+
| 15.01.2016 00:00:00 | 21.01.2016 00:00:00 |   3  |
+---------------------+---------------------+------+
| 22.01.2016 00:00:00 | 28.01.2016 00:00:00 |   4  |
+---------------------+---------------------+------+
| 29.01.2016 00:00:00 | 04.02.2016 00:00:00 |   5  |
+---------------------+---------------------+------+
| 05.02.2016 00:00:00 | 11.02.2016 00:00:00 |   6  |
+---------------------+---------------------+------+
| 12.02.2016 00:00:00 | 18.02.2016 00:00:00 |   7  |
+---------------------+---------------------+------+
| 19.02.2016 00:00:00 | 25.02.2016 00:00:00 |   8  |
+---------------------+---------------------+------+
| 26.02.2016 00:00:00 | 03.03.2016 00:00:00 |   9  |
+---------------------+---------------------+------+
| 04.03.2016 00:00:00 | 10.03.2016 00:00:00 |  10  |
+---------------------+---------------------+------+
| 11.03.2016 00:00:00 | 17.03.2016 00:00:00 |  11  |
+---------------------+---------------------+------+
| 18.03.2016 00:00:00 | 24.03.2016 00:00:00 |  12  |
+---------------------+---------------------+------+
| 25.03.2016 00:00:00 | 31.03.2016 00:00:00 |  13  |
+---------------------+---------------------+------+
| 01.04.2016 00:00:00 | 07.04.2016 00:00:00 |  14  |
+---------------------+---------------------+------+
| 08.04.2016 00:00:00 | 14.04.2016 00:00:00 |  15  |
+---------------------+---------------------+------+
| 15.04.2016 00:00:00 | 21.04.2016 00:00:00 |  16  |
+---------------------+---------------------+------+
| 22.04.2016 00:00:00 | 28.04.2016 00:00:00 |  17  |
+---------------------+---------------------+------+
| 29.04.2016 00:00:00 | 05.05.2016 00:00:00 |  18  |
+---------------------+---------------------+------+
| 06.05.2016 00:00:00 | 12.05.2016 00:00:00 |  19  |
+---------------------+---------------------+------+
| 13.05.2016 00:00:00 | 19.05.2016 00:00:00 |  20  |
+---------------------+---------------------+------+
| 20.05.2016 00:00:00 | 26.05.2016 00:00:00 |  21  |
+---------------------+---------------------+------+
| 27.05.2016 00:00:00 | 02.06.2016 00:00:00 |  22  |
+---------------------+---------------------+------+
| 03.06.2016 00:00:00 | 09.06.2016 00:00:00 |  23  |
+---------------------+---------------------+------+
| 10.06.2016 00:00:00 | 16.06.2016 00:00:00 |  24  |
+---------------------+---------------------+------+
| 17.06.2016 00:00:00 | 23.06.2016 00:00:00 |  25  |
+---------------------+---------------------+------+
| 24.06.2016 00:00:00 | 30.06.2016 00:00:00 |  26  |
+---------------------+---------------------+------+
| 01.07.2016 00:00:00 | 07.07.2016 00:00:00 |  27  |
+---------------------+---------------------+------+
| 08.07.2016 00:00:00 | 14.07.2016 00:00:00 |  28  |
+---------------------+---------------------+------+
| 15.07.2016 00:00:00 | 21.07.2016 00:00:00 |  29  |
+---------------------+---------------------+------+
| 22.07.2016 00:00:00 | 28.07.2016 00:00:00 |  30  |
+---------------------+---------------------+------+
| 29.07.2016 00:00:00 | 04.08.2016 00:00:00 |  31  |
+---------------------+---------------------+------+
| 05.08.2016 00:00:00 | 11.08.2016 00:00:00 |  32  |
+---------------------+---------------------+------+
| 12.08.2016 00:00:00 | 18.08.2016 00:00:00 |  33  |
+---------------------+---------------------+------+
| 19.08.2016 00:00:00 | 25.08.2016 00:00:00 |  34  |
+---------------------+---------------------+------+
| 26.08.2016 00:00:00 | 01.09.2016 00:00:00 |  35  |
+---------------------+---------------------+------+
| 02.09.2016 00:00:00 | 08.09.2016 00:00:00 |  36  |
+---------------------+---------------------+------+
| 09.09.2016 00:00:00 | 15.09.2016 00:00:00 |  37  |
+---------------------+---------------------+------+
| 16.09.2016 00:00:00 | 22.09.2016 00:00:00 |  38  |
+---------------------+---------------------+------+
| 23.09.2016 00:00:00 | 29.09.2016 00:00:00 |  39  |
+---------------------+---------------------+------+
| 30.09.2016 00:00:00 | 06.10.2016 00:00:00 |  40  |
+---------------------+---------------------+------+
| 07.10.2016 00:00:00 | 13.10.2016 00:00:00 |  41  |
+---------------------+---------------------+------+
| 14.10.2016 00:00:00 | 20.10.2016 00:00:00 |  42  |
+---------------------+---------------------+------+
| 21.10.2016 00:00:00 | 27.10.2016 00:00:00 |  43  |
+---------------------+---------------------+------+
| 28.10.2016 00:00:00 | 03.11.2016 00:00:00 |  44  |
+---------------------+---------------------+------+
| 04.11.2016 00:00:00 | 10.11.2016 00:00:00 |  45  |
+---------------------+---------------------+------+
| 11.11.2016 00:00:00 | 17.11.2016 00:00:00 |  46  |
+---------------------+---------------------+------+
| 18.11.2016 00:00:00 | 24.11.2016 00:00:00 |  47  |
+---------------------+---------------------+------+
| 25.11.2016 00:00:00 | 01.12.2016 00:00:00 |  48  |
+---------------------+---------------------+------+
| 02.12.2016 00:00:00 | 08.12.2016 00:00:00 |  49  |
+---------------------+---------------------+------+
| 09.12.2016 00:00:00 | 15.12.2016 00:00:00 |  50  |
+---------------------+---------------------+------+
| 16.12.2016 00:00:00 | 22.12.2016 00:00:00 |  51  |
+---------------------+---------------------+------+
| 23.12.2016 00:00:00 | 29.12.2016 00:00:00 |  52  |
+---------------------+---------------------+------+
| 30.12.2016 00:00:00 | 05.01.2017 00:00:00 |  53  |
+---------------------+---------------------+------+
| 06.01.2017 00:00:00 | 12.01.2017 00:00:00 |   1  |
+---------------------+---------------------+------+
| 13.01.2017 00:00:00 | 19.01.2017 00:00:00 |   2  |
+---------------------+---------------------+------+
| 20.01.2017 00:00:00 | 26.01.2017 00:00:00 |   3  |
+---------------------+---------------------+------+
| 27.01.2017 00:00:00 | 02.02.2017 00:00:00 |   4  |
+---------------------+---------------------+------+
| 03.02.2017 00:00:00 | 09.02.2017 00:00:00 |   5  |
+---------------------+---------------------+------+
| 10.02.2017 00:00:00 | 16.02.2017 00:00:00 |   6  |
+---------------------+---------------------+------+
| 17.02.2017 00:00:00 | 23.02.2017 00:00:00 |   7  |
+---------------------+---------------------+------+
| 24.02.2017 00:00:00 | 02.03.2017 00:00:00 |   8  |
+---------------------+---------------------+------+
| 03.03.2017 00:00:00 | 09.03.2017 00:00:00 |   9  |
+---------------------+---------------------+------+
| 10.03.2017 00:00:00 | 16.03.2017 00:00:00 |  10  |
+---------------------+---------------------+------+
| 17.03.2017 00:00:00 | 23.03.2017 00:00:00 |  11  |
+---------------------+---------------------+------+
| 24.03.2017 00:00:00 | 30.03.2017 00:00:00 |  12  |
+---------------------+---------------------+------+
| 31.03.2017 00:00:00 | 06.04.2017 00:00:00 |  13  |
+---------------------+---------------------+------+
| 07.04.2017 00:00:00 | 13.04.2017 00:00:00 |  14  |
+---------------------+---------------------+------+
| 14.04.2017 00:00:00 | 20.04.2017 00:00:00 |  15  |
+---------------------+---------------------+------+
| 21.04.2017 00:00:00 | 27.04.2017 00:00:00 |  16  |
+---------------------+---------------------+------+
| 28.04.2017 00:00:00 | 04.05.2017 00:00:00 |  17  |
+---------------------+---------------------+------+
| 05.05.2017 00:00:00 | 11.05.2017 00:00:00 |  18  |
+---------------------+---------------------+------+
| 12.05.2017 00:00:00 | 18.05.2017 00:00:00 |  19  |
+---------------------+---------------------+------+
| 19.05.2017 00:00:00 | 25.05.2017 00:00:00 |  20  |
+---------------------+---------------------+------+
| 26.05.2017 00:00:00 | 01.06.2017 00:00:00 |  21  |
+---------------------+---------------------+------+
| 02.06.2017 00:00:00 | 08.06.2017 00:00:00 |  22  |
+---------------------+---------------------+------+
| 09.06.2017 00:00:00 | 15.06.2017 00:00:00 |  23  |
+---------------------+---------------------+------+
| 16.06.2017 00:00:00 | 22.06.2017 00:00:00 |  24  |
+---------------------+---------------------+------+
| 23.06.2017 00:00:00 | 29.06.2017 00:00:00 |  25  |
+---------------------+---------------------+------+
| 30.06.2017 00:00:00 | 06.07.2017 00:00:00 |  26  |
+---------------------+---------------------+------+
| 07.07.2017 00:00:00 | 13.07.2017 00:00:00 |  27  |
+---------------------+---------------------+------+
| 14.07.2017 00:00:00 | 20.07.2017 00:00:00 |  28  |
+---------------------+---------------------+------+
| 21.07.2017 00:00:00 | 27.07.2017 00:00:00 |  29  |
+---------------------+---------------------+------+
| 28.07.2017 00:00:00 | 03.08.2017 00:00:00 |  30  |
+---------------------+---------------------+------+
| 04.08.2017 00:00:00 | 10.08.2017 00:00:00 |  31  |
+---------------------+---------------------+------+
| 11.08.2017 00:00:00 | 17.08.2017 00:00:00 |  32  |
+---------------------+---------------------+------+
| 18.08.2017 00:00:00 | 24.08.2017 00:00:00 |  33  |
+---------------------+---------------------+------+
| 25.08.2017 00:00:00 | 31.08.2017 00:00:00 |  34  |
+---------------------+---------------------+------+
| 01.09.2017 00:00:00 | 07.09.2017 00:00:00 |  35  |
+---------------------+---------------------+------+
| 08.09.2017 00:00:00 | 14.09.2017 00:00:00 |  36  |
+---------------------+---------------------+------+
| 15.09.2017 00:00:00 | 21.09.2017 00:00:00 |  37  |
+---------------------+---------------------+------+
| 22.09.2017 00:00:00 | 28.09.2017 00:00:00 |  38  |
+---------------------+---------------------+------+
| 29.09.2017 00:00:00 | 05.10.2017 00:00:00 |  39  |
+---------------------+---------------------+------+
| 06.10.2017 00:00:00 | 12.10.2017 00:00:00 |  40  |
+---------------------+---------------------+------+
| 13.10.2017 00:00:00 | 19.10.2017 00:00:00 |  41  |
+---------------------+---------------------+------+
| 20.10.2017 00:00:00 | 26.10.2017 00:00:00 |  42  |
+---------------------+---------------------+------+
| 27.10.2017 00:00:00 | 02.11.2017 00:00:00 |  43  |
+---------------------+---------------------+------+
| 03.11.2017 00:00:00 | 09.11.2017 00:00:00 |  44  |
+---------------------+---------------------+------+
| 10.11.2017 00:00:00 | 16.11.2017 00:00:00 |  45  |
+---------------------+---------------------+------+
| 17.11.2017 00:00:00 | 23.11.2017 00:00:00 |  46  |
+---------------------+---------------------+------+
| 24.11.2017 00:00:00 | 30.11.2017 00:00:00 |  47  |
+---------------------+---------------------+------+
| 01.12.2017 00:00:00 | 07.12.2017 00:00:00 |  48  |
+---------------------+---------------------+------+
| 08.12.2017 00:00:00 | 14.12.2017 00:00:00 |  49  |
+---------------------+---------------------+------+
| 15.12.2017 00:00:00 | 21.12.2017 00:00:00 |  50  |
+---------------------+---------------------+------+
| 22.12.2017 00:00:00 | 28.12.2017 00:00:00 |  51  |
+---------------------+---------------------+------+
| 29.12.2017 00:00:00 | 04.01.2018 00:00:00 |  52  |
+---------------------+---------------------+------+

【讨论】:

  • 无法从日期'2016-01-01'生成此表,错误代码530
【解决方案2】:

首先您需要一个函数来获取两个日期之间的天数,因此应创建以下函数:

CREATE FUNCTION [dbo].[GetDatesBetween](@dateFrom AS DATE, @dateTo AS DATE)
    returns table as
return (
    with 
     N0 as (SELECT 1 as n UNION ALL SELECT 1)
    ,N1 as (SELECT 1 as n FROM N0 t1, N0 t2)
    ,N2 as (SELECT 1 as n FROM N1 t1, N1 t2)
    ,N3 as (SELECT 1 as n FROM N2 t1, N2 t2)
    ,N4 as (SELECT 1 as n FROM N3 t1, N3 t2)
    ,N5 as (SELECT 1 as n FROM N4 t1, N4 t2)
    ,N6 as (SELECT 1 as n FROM N5 t1, N5 t2)
    ,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
    SELECT DATEADD(day,num-1,@dateFrom) as thedate
    FROM nums
    WHERE num <= DATEDIFF(day,@dateFrom,@dateTo) + 1
    );

然后,执行以下查询以获得所需的结果:

DECLARE @dteFROM DATE = '2016-01-01'
DECLARE @dteTo   DATE = '2017-01-26'

;WITH cteDaysInfo AS
(
    SELECT  theDate,
            YEAR(thedate) YearValue,
            DATEDIFF(day, CAST(YEAR(thedate) AS VARCHAR), CAST(YEAR(thedate) + 1 AS VARCHAR)) DaysInYear,
            datediff(week, CAST(YEAR(thedate) AS VARCHAR), CAST(YEAR(thedate) + 1 AS VARCHAR)) NumberOfWeeksInYear,
            ROW_NUMBER() OVER(ORDER BY theDate) DayNumberContinous,
            DATEPART(dayofyear, thedate) DayNumber,
            ceiling((ROW_NUMBER() OVER(ORDER BY theDate)) - 1) / 7 + 1 WeekNumberContinous,
            DATEPART(WEEK, theDate) WeekNumber
    FROM    dbo.GetDatesBetween(@dteFROM, @dteTo)
)

, cteBaseWeeksInfo AS
(
    SELECT  YearValue,
            (SELECT MIN(theDate) FROM cteDaysInfo t2 WHERE t2.YearValue = t1.YearValue and t2.WeekNumberContinous = t1.WeekNumberContinous) StartDate,
            (SELECT MAX(theDate) FROM cteDaysInfo t2 WHERE t2.YearValue = t1.YearValue and t2.WeekNumberContinous = t1.WeekNumberContinous) EndDate,
            t1.WeekNumberContinous,
            (SELECT MIN(WeekNumber) FROM cteDaysInfo t2 WHERE t2.YearValue = t1.YearValue and t2.WeekNumberContinous = t1.WeekNumberContinous) WeekNumber
    FROM    cteDaysInfo t1
    GROUP   BY YearValue, WeekNumberContinous
)

SELECT  (SELECT MIN(StartDate) FROM cteBaseWeeksInfo t2 WHERE t2.WeekNumberContinous = t1.WeekNumberContinous) StartDate,
        (SELECT MAX(EndDate) FROM cteBaseWeeksInfo t2 WHERE t2.WeekNumberContinous = t1.WeekNumberContinous) EndDate,
        (SELECT MAX(WeekNumber) FROM cteBaseWeeksInfo t2 WHERE t2.WeekNumberContinous = t1.WeekNumberContinous) EndDate
FROM    cteBaseWeeksInfo t1
GROUP   BY WeekNumberContinous

【讨论】:

  • 很好,但我需要一个简单的脚本。你创造了一个长的。
【解决方案3】:

以下解决方案不使用递归:

DECLARE @Year SMALLINT = 2016

DECLARE @FirstDayOfYear DATE = DATEFROMPARTS(@Year, 1, 1)
DECLARE @LastDayOfYear  DATE = DATEFROMPARTS(@Year, 12, 31)
DECLARE @FirstFriday    DATE = DATEADD(DAY, -3, DATEADD(WEEK, DATEDIFF(WEEK, '1900-01-01', @FirstDayOfYear), '1900-01-01'))

SET DATEFIRST 5
SELECT y.*, DATEPART(WEEK, y.FirstDayOfWeek) AS WeekNum
FROM (
    SELECT  FirstDayOfWeek  = DATEADD(WEEK, v.number, @FirstFriday), 
            LastDayOfWeek   = DATEADD(DAY, -1, DATEADD(WEEK, 1, DATEADD(WEEK, v.number, @FirstFriday))) 
    FROM    master.dbo.spt_values v -- Instead of this system table, a tally table could be used with all numbers from 0 to 100/1000/10000/etc. (min 54 values: [0..53])
    WHERE   v.type = 'P' -- number = [0..2048]
    AND     v.number <= 53) AS y
WHERE   @FirstDayOfYear <= y.LastDayOfWeek
AND     y.FirstDayOfWeek <= @LastDayOfYear

2016 年结果:

FirstDayOfWeek LastDayOfWeek WeekNum
-------------- ------------- -----------
2016-01-01     2016-01-07    1
2016-01-08     2016-01-14    2
2016-01-15     2016-01-21    3
2016-01-22     2016-01-28    4
2016-01-29     2016-02-04    5
...

2017 年结果:

FirstDayOfWeek LastDayOfWeek WeekNum
-------------- ------------- -----------
2016-12-30     2017-01-05    53
2017-01-06     2017-01-12    2
2017-01-13     2017-01-19    3
2017-01-20     2017-01-26    4
2017-01-27     2017-02-02    5
...

【讨论】:

  • 2017 年结果不正确。 017-01-06 和 2017-01-12 之间的日期范围为第一周。
  • 根据DATEPART(WEEK, _)函数,2017-01-06 2017-01-12 2是第二周。 ``ROW_NUMBER()` 函数可以在这里使用。
猜你喜欢
  • 2022-01-07
  • 2010-11-19
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多