【问题标题】:Generating Sequential Months in SQL在 SQL 中生成连续月份
【发布时间】:2020-03-01 13:31:41
【问题描述】:

我有一个如下示例的表格:

code |  date       | value
1000   2016-08-05    5000
1000   2016-12-27    8000
1000   2018-03-19    6000
1000   2018-06-02    6000

现在我需要像这样生成连续月份:

code |  date       | value
1000   2016-08-05    5000
1000   2016-09-05    5000
1000   2016-10-05    5000
1000   2016-11-05    5000
1000   2016-12-27    8000
1000   2017-01-27    8000
1000   2017-02-27    8000
........
1000   2018-03-19    6000
1000   2018-04-19    6000
1000   ....

序列一直持续到达到代码的最大日期。在此示例中,代码 1000 的最大日期为 2018-06-02。如何生成月份序列?任何帮助将不胜感激。

【问题讨论】:

  • 请阅读第一段sql tag infoedit你的问题。
  • @ZoharPeled 在说什么,用 SQL 示例更新您的问题,说明您已经尝试过什么以及什么不起作用。
  • 你的 MSSQL 版本是多少?

标签: sql-server tsql date datetime recursive-query


【解决方案1】:

试试这个:

DECLARE @DataSource TABLE
(
    [Code] INT
   ,[Date] DATE
   ,[value] INT
);

INSERT INTO @DataSource ([Code], [Date], [value])
VALUES (1000, '2016-08-05', 5000)
      ,(1000, '2016-12-27', 8000)
      ,(1000, '2018-03-19', 6000)
      ,(1000, '2018-06-02', 6000);

WITH Ranges AS
(
    SELECT *
          ,LEAD([Date]) OVER (ORDER BY [Date] ASC) AS [DateEnd]
    FROM @DataSource DS
)
SELECT *
FROM Ranges
CROSS APPLY
(
    SELECT DATEADD(MONTH, [number], [Date])
    FROM 
    (
        select number 
        from master.dbo.spt_values
        where [type] = 'P'
    ) numbers
    WHERE DATEADD(MONTH, [number], [Date]) < [DateEnd]
) AutoDates ([GeneratedDate]);

这个想法很简单——使用LEAD 获取日期范围的上限。然后有了开始和结束日期,只需使用DATEADD 函数生成缺失的月份。

【讨论】:

    【解决方案2】:

    一种解决方案是在递归 CTE 中创建一个数字表,然后与该表连接。您可以使用not exists 连接条件来定义每个系列的边界:我知道您每个月只需要一个日期(同一个月没有间隔和重叠),所以我使用了eomonth()

    查询:

    with nums(i) as (
        select 0
        union all select i + 1 from nums where i < 24
    )
    select 
        t.code,
        dateadd(month, i, t.date) date,
        t.value
    from mytable t
    inner join nums n 
        on not exists (
            select 1
            from mytable t1
            where t1.date > t.date and eomonth(t1.date) < eomonth(dateadd(month, i + 1, t.date))
        )
    order by date
    

    可以将cte中的上限延长到最大连续月数(我设置为24)。

    Demo on DB Fiddle

    代码 |日期 |价值 ---: | :----------------- | ----: 1000 | 05/08/2016 00:00:00 | 5000 1000 | 05/09/2016 00:00:00 | 5000 1000 | 2016 年 5 月 10 日 00:00:00 | 5000 1000 | 2016 年 5 月 11 日 00:00:00 | 5000 1000 | 27/12/2016 00:00:00 | 8000 1000 | 27/01/2017 00:00:00 | 8000 1000 | 27/02/2017 00:00:00 | 8000 1000 | 27/03/2017 00:00:00 | 8000 1000 | 27/04/2017 00:00:00 | 8000 1000 | 27/05/2017 00:00:00 | 8000 1000 | 27/06/2017 00:00:00 | 8000 1000 | 27/07/2017 00:00:00 | 8000 1000 | 27/08/2017 00:00:00 | 8000 1000 | 27/09/2017 00:00:00 | 8000 1000 | 27/10/2017 00:00:00 | 8000 1000 | 27/11/2017 00:00:00 | 8000 1000 | 27/12/2017 00:00:00 | 8000 1000 | 27/01/2018 00:00:00 | 8000 1000 | 27/02/2018 00:00:00 | 8000 1000 | 19/03/2018 00:00:00 | 6000 1000 | 19/04/2018 00:00:00 | 6000 1000 | 19/05/2018 00:00:00 | 6000 1000 | 02/06/2018 00:00:00 | 6000 1000 | 02/07/2018 00:00:00 | 6000 1000 | 02/08/2018 00:00:00 | 6000 1000 | 02/09/2018 00:00:00 | 6000 1000 | 2018 年 2 月 10 日 00:00:00 | 6000 1000 | 2018 年 2 月 11 日 00:00:00 | 6000 1000 | 2018 年 2 月 12 日 00:00:00 | 6000 1000 | 02/01/2019 00:00:00 | 6000 1000 | 02/02/2019 00:00:00 | 6000 1000 | 2019 年 2 月 3 日 00:00:00 | 6000 1000 | 02/04/2019 00:00:00 | 6000 1000 | 02/05/2019 00:00:00 | 6000 1000 | 02/06/2019 00:00:00 | 6000 1000 | 02/07/2019 00:00:00 | 6000 1000 | 02/08/2019 00:00:00 | 6000 1000 | 02/09/2019 00:00:00 | 6000 1000 | 02/10/2019 00:00:00 | 6000 1000 | 2019 年 2 月 11 日 00:00:00 | 6000 1000 | 2019 年 2 月 12 日 00:00:00 | 6000 1000 | 02/01/2020 00:00:00 | 6000 1000 | 02/02/2020 00:00:00 | 6000 1000 | 02/03/2020 00:00:00 | 6000 1000 | 02/04/2020 00:00:00 | 6000 1000 | 02/05/2020 00:00:00 | 6000 1000 | 02/06/2020 00:00:00 | 6000

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      • 2020-10-28
      • 1970-01-01
      相关资源
      最近更新 更多