Sql 常规?从2014年1月4日开始,我想知道每两个月的第二周星期六的日期。因此,如果1月1日至4日居住在1月1日的第一周,则为1月11日“。1月11日之后,我们将迎来3月8日,因为我认为3月1日也是第一周的第一个星期六。@pm-77-1对此表示抱歉,但请检查解

Sql 常规?从2014年1月4日开始,我想知道每两个月的第二周星期六的日期。因此,如果1月1日至4日居住在1月1日的第一周,则为1月11日“。1月11日之后,我们将迎来3月8日,因为我认为3月1日也是第一周的第一个星期六。@pm-77-1对此表示抱歉,但请检查解,sql,sql-server,sql-server-2008,tsql,datetime,Sql,Sql Server,Sql Server 2008,Tsql,Datetime,常规?从2014年1月4日开始,我想知道每两个月的第二周星期六的日期。因此,如果1月1日至4日居住在1月1日的第一周,则为1月11日“。1月11日之后,我们将迎来3月8日,因为我认为3月1日也是第一周的第一个星期六。@pm-77-1对此表示抱歉,但请检查解释中的粗体行和评论中最近的示例。您询问的是SQL/T-SQL解决方案,因此请将预期结果以表格形式添加到您的帖子中。”。 CREATE TABLE Calendar ( [Date] date NOT NULL, [NthWeek


常规?从2014年1月4日开始,我想知道每两个月的第二周星期六的日期。因此,如果1月1日至4日居住在1月1日的第一周,则为1月11日“。1月11日之后,我们将迎来3月8日,因为我认为3月1日也是第一周的第一个星期六。@pm-77-1对此表示抱歉,但请检查解释中的粗体行和评论中最近的示例。您询问的是SQL/T-SQL解决方案,因此请将预期结果以表格形式添加到您的帖子中。”。
CREATE TABLE Calendar
(
    [Date] date NOT NULL,
    [NthWeekdayInMonth] int,
    CONSTRAINT PK_Calendar
        PRIMARY KEY CLUSTERED ([Date])
        WITH FILLFACTOR = 100
)


;WITH cte AS 
(
    SELECT
        DATEADD(d, (a.Number * 256) + b.Number, '01/01/2000') AS [Date]
    FROM 
        (
            SELECT number
            FROM master..spt_values
            WHERE 
                type = 'P'
                AND number <= 255
        ) a (Number),
        (
            SELECT number
            FROM master..spt_values
            WHERE 
                type = 'P'
                AND number <= 255
        ) b (Number)
)

INSERT INTO Calendar
SELECT 
    [Date], 
    ROW_NUMBER() OVER (PARTITION BY YEAR([Date]), MONTH([Date]), DATEPART(dw, [Date]) ORDER BY [Date]) FROM cte
ORDER BY 
    [Date]
GO
2014-01-11 
2014-03-08 
2014-05-10 
2014-07-12
DECLARE @startDate date
DECLARE @everyNMonths int 
DECLARE @numResults int 
DECLARE @nthAppearanceOfDay int 

SET @startDate = '01/11/2014'   -- First occurence is on this date
SET @everyNMonths = 2           -- Skip every n months
SET @numResults = 4             -- Max # of results to return

-- Figure out which x-day of the month this is.  For example, if the starting 
-- date is 1/11/2014 that was the second Saturday so this will be set to 2.
SELECT @nthAppearanceOfDay = NthWeekdayInMonth FROM calendar WHERE [date] = @startDate

-- Use a CTE to get all the months involved in this calculation
;WITH candidateMonths AS (
    SELECT 
        1 AS [resultnum], @startDate AS [date]
    UNION ALL 
        SELECT resultnum + 1, DATEADD(month, @everyNMonths, [date]) FROM candidateMonths
            WHERE resultnum + 1 <= @numResults
)

-- Now evaluate every date for each of the candidate months.  If the day of week matches
-- that of the start date AND it is the Nth occurrence of that day of week in the month
-- include it
SELECT 
    c.[Date]
FROM 
    candidateMonths cm
    INNER JOIN calendar c ON ( (YEAR(c.[Date]) = YEAR(cm.[Date])) AND (MONTH(c.[Date]) = MONTH(cm.[Date])))
WHERE 
    (DATEPART(dw, c.[date]) = DATEPART(dw, @startDate)) -- Same day of week
    AND 
    (c.NthWeekdayInMonth = @nthAppearanceOfDay) -- Same week of month
SELECT * FROM dbo.NthWeekday(GETDATE(), 1, 1);
SELECT * FROM dbo.NthWeekday(GETDATE(), 1, -1);
DECLARE @date DATE = GETDATE();
DECLARE @numMonths INT = -5
DECLARE @weekday INT = 1;
DECLARE @n INT = 2;

SELECT C.D
FROM dbo.RangeSmallInt(0, @numMonths - SIGN(@numMonths)) A
CROSS APPLY ( -- MonthBegin
    SELECT DT = DATEADD(m, DATEDIFF(m, 0, @date) + A.N, 0)
) B
CROSS APPLY dbo.NthWeekday(B.DT, @weekday, @n) C;

Results: 2014-12-14
         2015-01-11
         2015-02-08
         2015-03-08
         2015-04-12
CREATE FUNCTION dbo.NthWeekday ( 
    @date DATE = NULL  
  , @weekday INT = NULL
  , @n INT = 1
)
RETURNS TABLE   
AS   
RETURN (
    SELECT D = CASE SIGN(@n)
                    WHEN -1 THEN DATEADD(d, -(DATEPART(dw, @date) + @@DATEFIRST - @weekday) % 7 + ((@n + 1) * 7), @date)                
                    ELSE DATEADD(d, (@weekday - DATEPART(dw, @date) + @@DATEFIRST) % 7 + ((@n - SIGN(@n)) * 7), @date)
               END
);
-- Generate a range of up to 65,536 contiguous BIGINTS
CREATE FUNCTION dbo.RangeSmallInt (
    @num1 BIGINT = NULL
  , @num2 BIGINT = NULL
)
RETURNS TABLE
AS
RETURN (
    WITH Numbers(N) AS (
        SELECT N FROM(VALUES
            (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 16
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 32
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 48
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 64
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 80
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 96
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 112
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 128
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 144
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 160
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 176
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 192
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 208
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 224
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 240
          , (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1) -- 256
        ) V (N)
    )    
    SELECT TOP (
               CASE
                   WHEN @num1 IS NOT NULL AND @num2 IS NOT NULL THEN ABS(@num1 - @num2) + 1
                   ELSE 0
               END
           )
           N = ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) + CASE WHEN @num1 <= @num2 THEN @num1 ELSE @num2 END - 1
    FROM Numbers A
       , Numbers B
    WHERE ABS(@num1 - @num2) + 1 < 65537
);