【问题标题】:Split multi-month records into individual months将多月记录拆分为单独的月份
【发布时间】:2020-10-19 00:08:16
【问题描述】:

我的表格中有这种格式的数据 - 日期范围是多月:

SourceSink  Class   ShadowPrice Round   Period  StartDate   EndDate
 AEC        Peak    447.038      3     WIN2020  2020-12-01  2021-02-28

我想创建一个视图/插入一个新表 - 上面的记录按月打破如下所示:

SourceSink  Class   ShadowPrice Round   Period  StartDate   EndDate
 AEC        Peak    447.038      3     WIN2020  2020-12-01  2021-12-31
 AEC        Peak    447.038      3     WIN2020  2021-01-01  2021-01-31
 AEC        Peak    447.038      3     WIN2020  2021-02-01  2021-02-28

请指教。

【问题讨论】:

  • 请向我们展示您的尝试。
  • 创建日历月表。加入条件是否月份与开始和结束重叠?

标签: sql sql-server date select recursive-query


【解决方案1】:

使用CROSS APPLY 和临时计数表的另一种选择

示例

Select A.[SourceSink]
      ,A.[Class]
      ,A.[ShadowPrice]
      ,A.[Round]
      ,A.[Period]
      ,B.[StartDate]
      ,B.[EndDate]
 From YourTable A
 Cross Apply (
                Select StartDate=min(D)
                      ,EndDate  =max(D)
                  From (
                         Select Top (DateDiff(DAY,[StartDate],[EndDate])+1) 
                                D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),[StartDate]) 
                          From  master..spt_values n1,master..spt_values n2
                       ) B1
                  Group By Year(D),Month(D)
             ) B

退货

【讨论】:

    【解决方案2】:

    一个选项是递归查询。假设周期总是从一个月的第一天开始,到一个月的最后一天结束,如您的示例数据所示,那就是:

    with cte as (
        select t.*, startDate newStartDate, eomonth(startDate) newEndDate
        from mytable t
        union all
        select 
            sourceSink,
            class,
            shadowPrice,
            period,
            startDate,
            endDate,
            dateadd(month, 1, newStartDate),
            eomonth(dateadd(month, 1, newStartDate))
        from cte
        where newStartDate < endDate
    )
    select * from cte
    

    如果周期在不同的月份开始和结束,那么我们需要更多的逻辑:

    with cte as (
        select 
            t.*, 
            startDate newStartDate, 
            case when eomonth(startDate) <= endDate then eomonth(startDate) else endDate end newEndDate
        from mytable t
        union all
        select 
            sourceSink,
            class,
            shadowPrice,
            period,
            startDate,
            endDate,
            dateadd(month, 1, datefromparts(year(newStartDate), month(newStartDate), 1)),
            case when eomonth(dateadd(month, 1, datefromparts(year(newStartDate), month(newStartDate), 1))) <= endDate
                then eomonth(dateadd(month, 1, datefromparts(year(newStartDate), month(newStartDate), 1)))
                else endDate
            end
        from cte
        where datefromparts(year(newStartDate), month(newStartDate), 1) < endDate
    )
    select * from cte
    

    【讨论】:

      猜你喜欢
      • 2019-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多