【问题标题】:SQL Server - Retrieve list of month dates between two columnsSQL Server - 检索两列之间的月份日期列表
【发布时间】:2021-12-30 08:32:18
【问题描述】:

我想添加一个新列,该列应包含两个单独列中的 startdate 和 enddate 之间的月份。

我当前的数据看起来像这样:

Case Name StartDate EndDate
1 ABC 2021-01-15 2021-03-15
2 DEF 2021-03-15 2021-05-15

我想要的输出是:

Case Name StartDate EndDate MonthList
1 ABC 2021-01-01 2021-03-15 2021-01-15
1 ABC 2021-01-01 2021-03-15 2021-02-15
1 ABC 2021-01-01 2021-03-15 2021-03-15
2 DEF 2021-03-01 2021-05-15 2021-03-15
2 DEF 2021-03-01 2021-05-15 2021-04-15
2 DEF 2021-03-01 2021-05-15 2021-05-15

【问题讨论】:

  • 请确保包括所有边缘情况,例如当范围小于一个月或一年以上,或者开始日期和结束日期不完全相隔一个月,或者任一日期落在 15 日以外的日期时。如果您只向我们展示您的两行,我们需要对所有其他行做出很多假设,而且我们错误的可能性要大于正确的可能性。

标签: sql sql-server date


【解决方案1】:

(编辑:Aaron 的评论是一个很好的观点 - 我已经做出了他所说的关于数据的确切假设 - 即,如果你的日期总是每个月的 15 日,这一切都很好。如果这不是真的,你可能有一些工作要做,所以要么改进你的问题,要么从这个起点自己解决)

这应该可以得到你想要的

CREATE TABLE #data
(
    [Case] INT,
    Name    VARCHAR(3),
    StartDate DATE,
    EndDate DATE
);

INSERT INTO #data
VALUES
(1,'ABC','2021-01-15','2021-03-15'),
(2,'DEF','2021-03-15','2021-05-15');

WITH cte([Case], [Name], dt) AS 
(
    SELECT [Case], [Name], StartDate AS dt
    FROM #data 
    UNION ALL
    SELECT cte.[Case], cte.Name, DATEADD(MONTH, 1, dt)
    FROM cte 
    INNER JOIN #data ON #data.[Case] = cte.[Case] AND #data.[Name] = cte.[Name]
    WHERE dt < EndDate
)
SELECT *
FROM cte
ORDER BY cte.[Case], cte.Name, cte.dt

但实际上像这样的递归查询很难维护。我会创建一个包含几个月负载的“月份”表,然后您可以加入月份在 StartDate 和 EndDate 之间的那个:

CREATE TABLE #months -- This would be a concrete table in your db, not temp
(
    MonthDate DATE
)

INSERT INTO #months -- you would need to populate this with enough months to satisfy your needs
VALUES 
('2021-01-15'),
('2021-02-15'),
('2021-03-15'),
('2021-04-15'),
('2021-05-15'),
('2021-06-15');

SELECT d.[Case], d.[Name], m.MonthDate
FROM #data d
INNER JOIN #months m ON m.MonthDate BETWEEN d.StartDate AND d.EndDate
ORDER BY d.[Case], d.[Name], m.MonthDate

【讨论】:

    【解决方案2】:

    见 (Generate Dates between date ranges)
    使用交叉连接将您的 tmp 表与日期生成器代码结合起来

    declare @tmp as table ( [Case] int, [Name] varchar(20), [StartDate] date, [EndDate] date)
    
    insert into @tmp
    values(1,   'ABC',  '2021-01-15',   '2021-03-15')
    ,(2,    'DEF'   ,'2021-03-15',  '2021-05-15')
    
    
    SELECT  
    tmp.[Case],
    tmp.[Name],
    DATEADD(DAY, Nbr - 1, tmp.StartDate) MonthList
    FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY c.object_id ) AS Nbr
              FROM      sys.columns c
            ) nbrs
            cross join
            (
                select [Name],[Case],[StartDate],[EndDate] from @tmp
            )tmp
    WHERE   Nbr - 1 <= DATEDIFF(DAY, tmp.StartDate, tmp.EndDate)
    order by
    tmp.[Case],
    tmp.[Name],
    Detail_Date
    

    输出:

        Case    Name    MonthList
    1   ABC 2021-01-15
    1   ABC 2021-01-16
    1   ABC 2021-01-17
    1   ABC 2021-01-18
    1   ABC 2021-01-19
    1   ABC 2021-01-20
    1   ABC 2021-01-21
    1   ABC 2021-01-22
    1   ABC 2021-01-23
    1   ABC 2021-01-24
    1   ABC 2021-01-25
    1   ABC 2021-01-26
    1   ABC 2021-01-27
    1   ABC 2021-01-28
    1   ABC 2021-01-29
    1   ABC 2021-01-30
    1   ABC 2021-01-31
    1   ABC 2021-02-01
    1   ABC 2021-02-02
    1   ABC 2021-02-03
    1   ABC 2021-02-04
    1   ABC 2021-02-05
    1   ABC 2021-02-06
    1   ABC 2021-02-07
    1   ABC 2021-02-08
    1   ABC 2021-02-09
    1   ABC 2021-02-10
    1   ABC 2021-02-11
    1   ABC 2021-02-12
    1   ABC 2021-02-13
    1   ABC 2021-02-14
    1   ABC 2021-02-15
    1   ABC 2021-02-16
    1   ABC 2021-02-17
    1   ABC 2021-02-18
    1   ABC 2021-02-19
    1   ABC 2021-02-20
    1   ABC 2021-02-21
    1   ABC 2021-02-22
    1   ABC 2021-02-23
    1   ABC 2021-02-24
    1   ABC 2021-02-25
    1   ABC 2021-02-26
    1   ABC 2021-02-27
    1   ABC 2021-02-28
    1   ABC 2021-03-01
    1   ABC 2021-03-02
    1   ABC 2021-03-03
    1   ABC 2021-03-04
    1   ABC 2021-03-05
    1   ABC 2021-03-06
    1   ABC 2021-03-07
    1   ABC 2021-03-08
    1   ABC 2021-03-09
    1   ABC 2021-03-10
    1   ABC 2021-03-11
    1   ABC 2021-03-12
    1   ABC 2021-03-13
    1   ABC 2021-03-14
    1   ABC 2021-03-15
    2   DEF 2021-03-15
    2   DEF 2021-03-16
    2   DEF 2021-03-17
    2   DEF 2021-03-18
    2   DEF 2021-03-19
    2   DEF 2021-03-20
    2   DEF 2021-03-21
    2   DEF 2021-03-22
    2   DEF 2021-03-23
    2   DEF 2021-03-24
    2   DEF 2021-03-25
    2   DEF 2021-03-26
    2   DEF 2021-03-27
    2   DEF 2021-03-28
    2   DEF 2021-03-29
    2   DEF 2021-03-30
    2   DEF 2021-03-31
    2   DEF 2021-04-01
    2   DEF 2021-04-02
    2   DEF 2021-04-03
    2   DEF 2021-04-04
    2   DEF 2021-04-05
    2   DEF 2021-04-06
    2   DEF 2021-04-07
    2   DEF 2021-04-08
    2   DEF 2021-04-09
    2   DEF 2021-04-10
    2   DEF 2021-04-11
    2   DEF 2021-04-12
    2   DEF 2021-04-13
    2   DEF 2021-04-14
    2   DEF 2021-04-15
    2   DEF 2021-04-16
    2   DEF 2021-04-17
    2   DEF 2021-04-18
    2   DEF 2021-04-19
    2   DEF 2021-04-20
    2   DEF 2021-04-21
    2   DEF 2021-04-22
    2   DEF 2021-04-23
    2   DEF 2021-04-24
    2   DEF 2021-04-25
    2   DEF 2021-04-26
    2   DEF 2021-04-27
    2   DEF 2021-04-28
    2   DEF 2021-04-29
    2   DEF 2021-04-30
    2   DEF 2021-05-01
    2   DEF 2021-05-02
    2   DEF 2021-05-03
    2   DEF 2021-05-04
    2   DEF 2021-05-05
    2   DEF 2021-05-06
    2   DEF 2021-05-07
    2   DEF 2021-05-08
    2   DEF 2021-05-09
    2   DEF 2021-05-10
    2   DEF 2021-05-11
    2   DEF 2021-05-12
    2   DEF 2021-05-13
    2   DEF 2021-05-14
    2   DEF 2021-05-15
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多