如何使用sql查询在2个日期之间准确计算第2和第4个星期六

时间:2016-09-23 13:58:38

标签: sql-server tsql

我想获得第二和第四周六的数字 两个日期之间

例如:

DECLARE @FromDate date='08/01/2016' 
DECLARE @ToDate date='09/20/2016' 

请帮帮我 提前谢谢..

3 个答案:

答案 0 :(得分:1)

我使用UDF创建动态日期范围,但是Tally / Date Table也可以做到这一点

with cteBase as (
    Select * 
          ,RowNr=Row_Number() over (Order by RetVal)
      From [dbo].[udf-Create-Range-Date]('2016-08-01','2016-09-20','DD',1) 
      Where DateName(DW,RetVal)='Saturday'
)
Select RetVal From cteBase Where RowNr in (2,4)

返回

RetVal
2016-08-13 00:00:00.000
2016-08-27 00:00:00.000

UDF(如果需要)

CREATE FUNCTION [dbo].[udf-Create-Range-Date] (@DateFrom datetime,@DateTo datetime,@DatePart varchar(10),@Incr int)

Returns 
@ReturnVal Table (RetVal datetime)

As
Begin
    With DateTable As (
        Select DateFrom = @DateFrom
        Union All
        Select Case @DatePart
               When 'YY' then DateAdd(YY, @Incr, df.dateFrom)
               When 'QQ' then DateAdd(QQ, @Incr, df.dateFrom)
               When 'MM' then DateAdd(MM, @Incr, df.dateFrom)
               When 'WK' then DateAdd(WK, @Incr, df.dateFrom)
               When 'DD' then DateAdd(DD, @Incr, df.dateFrom)
               When 'HH' then DateAdd(HH, @Incr, df.dateFrom)
               When 'MI' then DateAdd(MI, @Incr, df.dateFrom)
               When 'SS' then DateAdd(SS, @Incr, df.dateFrom)
               End
        From DateTable DF
        Where DF.DateFrom < @DateTo
    )

    Insert into @ReturnVal(RetVal) Select DateFrom From DateTable option (maxrecursion 32767)

    Return
End

-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','YY',1) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','DD',1) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-31','MI',15) 
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-02','SS',1) 
  

编辑以在范围内每周六返回

with cteBase as (
    Select * 
          ,RowNr=Row_Number() over (Order by RetVal)
      From [dbo].[udf-Create-Range-Date]('2016-09-17','2016-10-29','DD',1)
      Where DateName(DW,RetVal)='Saturday'
)
Select RetVal From cteBase Where RowNr % 2 = 0

返回

RetVal
2016-09-24 00:00:00.000
2016-10-08 00:00:00.000
2016-10-22 00:00:00.000

答案 1 :(得分:0)

你应养成创建Calendar表的习惯。如果您根据日期处理大量差距和岛屿问题或进行大量以日期为中心的处理,它将节省大量时间。与此同时,我建议你在此期间建立一个内存表来处理你的查询。

DECLARE @DATES TABLE
(
    Day INT,
    Month INT,
    Year INT,
    DayInWeek INT,
    WeekInYear INT
    CalendarDate DATETIME
)

DECLARE @FromDate date='08/01/2016' 
DECLARE @ToDate date='09/20/2016' 

WHILE(@FromDate<=@ToDate) BEGIN
   INSERT INTO @DATE DATEPART(DAY,@FromDate....)
   SET @FromDate=DATEADD(DAY,1,@FromDate)
END

    SELECT
      *
    FROM
    (
        SELECT 
           *
        FROM
           @DATE D
           LEFT OUTER JOIN
           (
             ...My Query
           ) MQ ON MQ.Date=D.CalendarDate 
    )AS X        

答案 2 :(得分:0)

declare @startDate datetime = '2016-09-16'
declare @endDate datetime = '2016-10-12'
declare @DayName Varchar(20) = 'Saturday'
declare @SelectionType Varchar(20) = '1 And 4'
-- '1 And 4','1 And 3','2 And 4','All' we can pass what ever we want
declare @MothstartDateofStartDate datetime
SELECT @MothstartDateofStartDate = DATEADD(month, DATEDIFF(month, 0, @startDate), 0)-1

;with dateRange as
(
  select [Date] = dateadd(dd, 1, @MothstartDateofStartDate), datename(dw,dateadd(dd, 1, @MothstartDateofStartDate)) [DayName]
  where dateadd(dd, 1, @MothstartDateofStartDate) < @endDate
  union all
  select dateadd(dd, 1, [Date]), datename(dw,dateadd(dd, 1, [Date])) [DayName]
  from dateRange
  where dateadd(dd, 1, [Date]) < @endDate
)
select count(*) from (
select [Date],T0.[DayName],(select count(*) from dateRange T1 
where T1.Date between  DATEADD(month, DATEDIFF(month, 0, T0.Date), 0) and T0.Date And T1.[DayName] =T0.[DayName] 
group By T1.[DayName]) PlaceCount
from dateRange T0 where T0.Date >=@startDate ) AA
where AA.[DayName]= @DayName 
and 
'True'=case when @SelectionType ='1 And 4' then case when PlaceCount in(1,4) then 'True' else 'False' end
when @SelectionType ='1 And 3' then case when PlaceCount in(1,3) then 'True' else 'False' end
when @SelectionType ='2 And 4' then case when PlaceCount in(2,4) then 'True' else 'False' end
when @SelectionType ='All' then  'True' end