在SQL中两个日期之间获取一周的开始日期和结束日期的最佳方法是什么

时间:2012-10-05 18:37:36

标签: sql sql-server sql-server-2005

我使用SQL Server 2005.我有一个开始和结束日期。

例如:

START_DATE    END_DATE
2011-04-24    2012-05-05 

我希望在两个日期之间获得所有开始日(SQL设置为星期日)和每周结束日(星期六)。

期望的结果:

2011-04-24    2011-04-30
2011-05-01    2011-05-07
2011-05-08    2011-05-14
....
2012-04-29    2012-05-05

现在我知道我可以做DATEADD(week, 1, 2011-04-24)之类的事情,直到我到达我的结束日期,但是直到我到达我的结束日期(没有光标或一段时间)我都不知道该怎么做)。我想在一个查询中完成。

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:4)

使用日期功能是一种智能且前瞻性的选择。在sqlteam上有一个很棒的F_TABLE_DATE

我提取了相关的代码片段,以说明如何将其作为一次性利用:

declare @sDate datetime,
        @eDate datetime;

select  @sDate = '2011-04-24',
        @eDate = '2012-05-05';

;with AllDatesBetween (d)
as  (   
        select dateadd(dd, n-1, @sDate)
        from    util.Number
        where   n <= datediff(dd, @sDate, @eDate+1)
    )
select  distinct
        dateadd(dd,(datediff(dd,'17530107',d)/7)*7,'17530107') [weekStart],
        dateadd(dd,((datediff(dd,'17530107',d)/7)*7)+6,'17530107') [weekEnd]
from    AllDatesBetween
order
by      1,2

答案 1 :(得分:1)

我还将分享一组我使用的常用日期函数。只需将其创建为表值函数:

    set ANSI_NULLS ON
    set QUOTED_IDENTIFIER ON
    go

    CREATE FUNCTION [dbo].[udfCommonDates] (@date datetime)
    RETURNS @t table (week_start datetime,
                      week_end datetime,
                      lastweek_start datetime,
                      lastweek_end datetime,
                      month_start datetime,
                      month_end datetime,
                      lastmonth_start datetime,
                      lastmonth_end datetime,
                      yesterday_start datetime,
                      yesterday_end datetime,
                      today_start datetime,
                      today_end datetime,
                      thisweek_monday_start datetime,
                      thisweek_monday_end datetime,
                      year_start datetime,
                      year_end datetime,
                      tomorrow_noon datetime,
                      today_noon datetime,
                      date_only datetime)
    BEGIN
       INSERT @t
       SELECT
       dbo.get_week_start ( @date ) AS week_start,
       dbo.get_week_end   ( @date ) AS week_end,
       dbo.get_week_start ( DATEADD(d, -7, @date ) ) AS lastweek_start,
       dbo.get_week_end   ( DATEADD(d, -7, @date ) ) AS lastweek_end,
       dbo.get_month_start( @date ) AS month_start,
       dbo.get_month_end  ( @date ) AS month_end,
       dbo.get_month_start ( DATEADD(m,-1, @date) ) AS lastmonth_start,
       dbo.get_month_end  ( DATEADD(m,-1,@date) ) AS lastmonth_end,
       dbo.get_yesterday_start ( @date ) AS yesterday_start,
       dbo.get_yesterday_end ( @date ) AS yesterday_end,
       dbo.get_today_start (@date) AS today_start,
       dbo.get_today_end ( @date ) AS today_end,
       dbo.get_weekday_start(1,@date) AS thisweek_monday_start,
       dbo.get_weekday_end(1,@date) AS thisweek_monday_end,
       dbo.get_year_start(@date) AS year_start,
       dbo.get_year_end(@date) AS year_end,  
       dbo.get_tomorrow_noon(@date) AS TomorrowNoon,
       dbo.get_today_noon(@date) AS TodayNoon,
       dbo.get_date_only(@date) AS DateOnly
    RETURN
    END

以下是这些的标量值函数:

   CREATE FUNCTION [dbo].[get_date_only] (@date datetime)
    RETURNS datetime
    WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
    AS    
    BEGIN
        RETURN dateadd(day, DateDiff(day, 0, GetDate()), 0)
    END
    GO

CREATE FUNCTION [dbo].[get_month_end] (@date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    
BEGIN
   RETURN dateadd(ms, -3, dateadd (m,datediff(m,0,
          dateadd(m,1,@date)),0))
END
GO

CREATE FUNCTION [dbo].[get_month_start] (@date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    
BEGIN
   RETURN dateadd(m,datediff(m,0, @date),0)
   END
GO

CREATE FUNCTION [dbo].[get_today_end] (@today datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    
BEGIN
   return dateadd(ms, -3, datediff(d,0,dateadd(d,1,@today)))
END
GO

CREATE FUNCTION [dbo].[get_today_noon](@date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   RETURN DATEADD(hh, 12, DATEADD(d,DATEDIFF(d,0, @date),0))
END
GO

CREATE FUNCTION [dbo].[get_today_start] (@today datetime)
RETURNS datetime 
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   return dateadd(day, 0, datediff(d,0,@today))
END
GO

CREATE FUNCTION [dbo].[get_tomorrow_noon](@date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   RETURN DATEADD(hh, 12, DATEADD(d,DATEDIFF(d,-1, @date),0))
END
GO

CREATE FUNCTION [dbo].[get_week_end] (@date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   return dateadd(yyyy, datepart(yyyy,
      dateadd(weekday,7-datepart(weekday, @date),@date))-1900, 0)
    + dateadd(ms, -3,
      dateadd(dy, datepart(dy,
     dateadd(weekday,7-datepart(weekday, @date),@date)),0) )
END
GO

CREATE FUNCTION [dbo].[get_week_start] (@date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   return dateadd(yyyy, datepart(yyyy,
      dateadd(weekday,1-datepart(weekday, @date),@date))-1900, 0)
    + dateadd(dy, datepart(dy,
      dateadd(weekday,1-datepart(weekday, @date),@date))-1,0)
END
GO

CREATE FUNCTION [dbo].[get_weekday_end] (@weekday tinyint,
                                 @date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   return dateadd(yyyy, datepart(yyyy,
      dateadd(weekday,@weekday-
      datepart(weekday, @date),@date))-1900, 0)
    + dateadd(ms, -3,
      dateadd(dy, datepart(dy,
      dateadd(weekday,@weekday-datepart(weekday, @date),
                                        @date)),0) )
END
GO

CREATE FUNCTION [dbo].[get_weekday_start] (@weekday tinyint,
                                   @date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   return dateadd(yyyy, datepart(yyyy,
      dateadd(weekday,@weekday-
      datepart(weekday, @date),@date))-1900, 0)
    + dateadd(dy, datepart(dy,
      dateadd(weekday,@weekday-datepart(weekday, @date),
                                        @date))-1,0)
END
GO

CREATE FUNCTION [dbo].[get_year_end] (@date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
RETURN DATEADD(year, DATEDIFF(year, 0, GetDate())+1, 0)-1
END
GO

CREATE FUNCTION [dbo].[get_year_start] (@date datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   RETURN DATEADD(year,DATEDIFF(year,0, @date),0)
END
GO

CREATE FUNCTION [dbo].[get_yesterday_end] (@today datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   return dateadd(ms, -3, datediff(d,0,@today))
END
GO

CREATE FUNCTION [dbo].[get_yesterday_start] (@today datetime)
RETURNS datetime
WITH SCHEMABINDING, RETURNS NULL ON NULL INPUT
AS    BEGIN
   RETURN dateadd(day, -1, datediff(d,0,@today))
END
GO

你可以像这样执行整个表值函数:

SELECT * FROM [MyDB].[dbo].[udfCommonDates] (GetDate())

答案 2 :(得分:0)

刚刚找到了一种方法来实现递归!

;WITH DaysOfWeek AS 
( 
    SELECT {d '2011-04-24'} AS StartOfWeek
    UNION ALL 
    SELECT DATEADD( week, 1, jdr.StartOfWeek) AS StartOfWeek
    FROM JoursDuReleve jdr 
    WHERE DATEADD(week, 1, jdr.StartOfWeek) <= {d '2012-05-05'}
) 
SELECT StartOfWeek, DATEADD(day, 6, StartOfWeek) AS EndOfWeek  
FROM DaysOfWeek
ORDER BY StartOfWeek DESC 
OPTION (MAXRECURSION 0)