SQL - 在两个日期之间创建自定义日期列表

时间:2015-12-14 10:40:40

标签: sql sql-server

我在编译查询时遇到的问题比执行以下操作有困难:

  1. 我的桌子有 startDate endDate [tblPayments]
  2. 我有一个专栏 paymentDay [tblPayments]
  3. 数据

    paymentID        startDate           endDate          paymentDay
        1            2016-01-01         2016-12-31            25
        2            2015-06-01         2016-06-30            16
    

    我正在尝试生成SELECT查询,该查询会根据这两个日期之间的月份将此特定表拆分为单独的行,并将 paymentDay 设置为这些查询

    示例输出

    paymentID       expectedDate
        1            2016-01-25   
        1            2016-02-25   
        1            2016-03-25   
        1            2016-04-25   
        1            2016-05-25   
        1            2016-06-25   
        1            2016-07-25   
        1            2016-08-25   
        1            2016-09-25   
        1            2016-10-25   
        1            2016-11-25   
        1            2016-12-25   
        2            2015-06-16   
        2            2015-07-16  
        2            2015-08-16  
        2            2015-09-16  
        2            2015-10-16  
        2            2015-11-16  
        2            2015-12-16  
        2            2016-01-16  
        2            2016-02-16  
        2            2016-03-16  
        2            2016-04-16  
        2            2016-05-16  
    

    我找到了一个查询,它会选择这些日期之间的月份,但是它会调整到上面的表格,以及我正在努力的多个startDates和endDates

    分割月份

    declare @start DATE = '2015-01-01'
    declare @end DATE = '2015-12-31'
    
    ;with months (date)
    AS
    (
        SELECT @start
        UNION ALL
        SELECT DATEADD(MM,1,date)
        from months
        where DATEADD(MM,1,date)<=@end
    )
    select Datename(MM,date) from months
    

    此查询仅限于一个 startDate endDate ,因此我尚未对其进行扩展以更改日期的 DAY

2 个答案:

答案 0 :(得分:2)

使用日期表和简单的内部联接

DECLARE @tblPayments table (paymentID int identity(1,1), startDate date, endDate date, paymentDay int)

INSERT @tblPayments VALUES 
  ('2016-01-01', '2016-12-31', 25), 
  ('2015-06-01', '2016-06-30', 16)



;WITH dates AS -- Build date within the range of startDate and endDate
(
    SELECT MIN(startDate) AS Value, MAX(endDate) AS MaxDate FROM @tblPayments
    UNION ALL 
    SELECT DATEADD(DAY, 1, Value), MaxDate 
    FROM dates WHERE DATEADD(DAY, 1, Value) <= MaxDate
)
SELECT pay.paymentID, dates.Value AS expectedDate 
FROM 
    @tblPayments pay 
    INNER JOIN dates ON 
        dates.Value BETWEEN pay.startDate AND pay.endDate 
        AND DAY(dates.Value) = paymentDay
OPTION (maxrecursion 0)

答案 1 :(得分:1)

我会创建一个内存日历表,然后通过加入它来执行一个简单的查询:

-- Create a table with all the dates between the min and max dates in the 
-- data table
DECLARE @Calendar TABLE
(
    [CalendarDate] DATETIME
)

DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SELECT @StartDate = MIN(startdate), @EndDate = MAX(enddate) FROM YourDataTable

WHILE @StartDate <= @EndDate
BEGIN
    INSERT INTO @Calendar (CalendarDate)
    SELECT @StartDate
    SET @StartDate = DATEADD(dd, 1, @StartDate)
END

-- Join to return only dates between the start and end date that match the Payment Day
SELECT D.PaymentId, C.CalendarDate FROM YourDataTable D
INNER JOIN @Calendar C ON C.CalendarDate BETWEEN D.StartDate AND D.EndDate
AND DATEPART(day, C.CalendarDate) = D.PaymentDay