【问题标题】:MS SQL Server 2008 :Getting start date and end date of the week to next 8 weeksMS SQL Server 2008:获取一周的开始日期和结束日期到接下来的 8 周
【发布时间】:2013-03-21 09:44:14
【问题描述】:

我是 SQL 新手,谁能给我查询这个场景“我需要显示从今天开始到接下来 8 周的一周的开始日期和结束日期”。例如,如果我选择今天的日期,它应该显示

  1. 开始日期 |结束日期
  2. 17/03/2012 | 23/03/2012
  3. 2012 年 3 月 24 日 | 29/03/2012
  4. ..等
  5. 28/04/2012 |03/05/2013

【问题讨论】:

    标签: sql sql-server-2008 tsql


    【解决方案1】:

    试试这个:

    DECLARE @startDate DATETIME
    DECLARE @currentDate DATETIME
    DECLARE @numberOfWeeks INT
    
    DECLARE @dates TABLE(
        StartDate DateTime,
        EndDate DateTime 
    )
    
    SET @startDate = GETDATE()--'2012-01-01' -- Put whatever you want here
    SET @numberOfWeeks = 8 -- Choose number of weeks here
    SET @currentDate = @startDate
    
    while @currentDate < dateadd(week, @numberOfWeeks, @startDate)
    begin
        INSERT INTO @Dates(StartDate, EndDate) VALUES (@currentDate, dateadd(day, 6, @currentDate))
        set @currentDate = dateadd(day, 7, @currentDate);
    end
    
    SELECT * FROM @dates
    

    这会给你这样的东西:

    StartDate           EndDate 
    21/03/2013 11:22:46 27/03/2013 11:22:46 
    28/03/2013 11:22:46 03/04/2013 11:22:46 
    04/04/2013 11:22:46 10/04/2013 11:22:46 
    11/04/2013 11:22:46 17/04/2013 11:22:46 
    18/04/2013 11:22:46 24/04/2013 11:22:46 
    25/04/2013 11:22:46 01/05/2013 11:22:46 
    02/05/2013 11:22:46 08/05/2013 11:22:46 
    09/05/2013 11:22:46 15/05/2013 11:22:46 
    

    如果您不想要时间组件,也可以调整最终选择,如下所示:

    SELECT CONVERT(VARCHAR, StartDate, 103), CONVERT(VARCHAR, EndDate, 103) FROM @dates
    

    【讨论】:

      【解决方案2】:

      您可以查看这篇 StackOverFlow 帖子: Generate a resultset of incrementing dates in TSQL

      以下应该会给你这个结果:

      declare @dateIterator datetime = getdate();
      declare @endDate datetime = dateadd(week, 8, getdate());
      declare @dateRange varchar(max) = '';
      
      while @dateIterator < @endDate
      begin
          set @dateIterator = dateadd(day, 1, @dateIterator);
          set @dateRange = @dateRange + ' ' + convert(varchar(10), @dateIterator, 3)
      end
      
      select @dateRange
      

      希望这会有所帮助!

      【讨论】:

      • 对不起,我需要两列,一是开始日期,一是特定周的结束日期
      【解决方案3】:

      如果您想避免迭代(例如,如果您需要在视图中使用此数据),您可以使用以下技术:

      ;WITH w(weeknumber) AS
          (SELECT 0
              UNION SELECT 1
              UNION SELECT 2
              UNION SELECT 3
              UNION SELECT 4
              UNION SELECT 5
              UNION SELECT 6
              UNION SELECT 7), 
       f(firstdayofweek) AS
           (SELECT DATEADD(ww,DATEDIFF(ww,0,GETDATE()),0)),
       o(offsetweekdate) AS
           (SELECT DATEADD(ww,w.weeknumber,f.firstdayofweek) FROM w,f)
      SELECT
          DATEADD(d,0,o.offsetweekdate) AS firstdayofweek,
          DATEADD(d,6,o.offsetweekdate) AS lastdayofweek
      FROM o
      

      这里,w 生成从 0 到 7 的数字列表,f 找到一周的第一天,o 将这两者结合起来给出接下来 8 周的开始和结束日期周。

      这样做的缺点是,要增加预计转发的周数,您需要在 w 的定义中添加额外的一行。这是因为没有内置方法可以在不使用循环的情况下使用 TSQL 生成一系列值。

      Jeff Moden 发布了一个非常有用的范围函数 elsewhere on StackOverflow,我喜欢在这类场景中使用它。

      CREATE FUNCTION [dbo].[Range](@startvalue integer,@endvalue integer)
      RETURNS TABLE
      AS 
      RETURN(
      WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
           E02(N) AS (SELECT 1 FROM E00 a, E00 b),
           E04(N) AS (SELECT 1 FROM E02 a, E02 b),
           E08(N) AS (SELECT 1 FROM E04 a, E04 b),
           E16(N) AS (SELECT 1 FROM E08 a, E08 b),
           E32(N) AS (SELECT 1 FROM E16 a, E16 b),
      cteTally(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
      SELECT TOP (@endvalue-@startvalue+1) (N+@startvalue-1) AS Number
          FROM cteTally
      WHERE N <= (@endvalue-@startvalue+1))
      

      这允许您使用简单的SELECT Number FROM RANGE(0,10) 生成范围。一旦你定义了这个函数,原始代码可以简化为:

      ;WITH w(weeknumber) AS
          (SELECT Number FROM Range(0,7)), 
       f(firstdayofweek) AS
           (SELECT DATEADD(ww,DATEDIFF(ww,0,GETDATE()),0)),
       o(offsetweekdate) AS
           (SELECT DATEADD(ww,w.weeknumber,f.firstdayofweek) FROM w,f)
      SELECT
          DATEADD(d,0,o.offsetweekdate) AS firstdayofweek,
          DATEADD(d,6,o.offsetweekdate) AS lastdayofweek
      FROM o
      

      然后,将其扩展为采用参数表示向前投射的周数将是一个简单的更改。

      【讨论】: