【问题标题】:Get all the dates between two successive dates in same column for a specific group获取特定组的同一列中两个连续日期之间的所有日期
【发布时间】:2020-03-02 15:21:07
【问题描述】:

我有一个这样的市场表 (#Market):

对于市场的每个交货日期,我需要生成直到该市场下一个交货日期的日期。所需的输出应如下所示:

我尝试根据所有市场的最大和最小日期范围获取日历日期,然后尝试将日期与市场交货日期匹配。

日历日期(#Calendar)生成如下:

Date
2020-03-01
2020-03-02
2020-03-03
2020-03-04
2020-03-05
2020-03-06
2020-03-07
2020-03-08
2020-03-09
2020-03-10
2020-03-11
2020-03-12
2020-03-13
2020-03-14
2020-03-15

但我找不到将日历表与市场表进行比较并获取每个交货日期和市场的连续行之间的日期的方法。下面的交叉连接为我提供了特定交货日期之后的所有日期,但不能限制到该市场的下一个交货日期。

select * from #Calendar c
    cross join #Market  m
    where date>=[Delivery Date]
    order by marketid,[Delivery Date]

有没有办法在特定市场的下一个交货日期之前限制这些日期?

【问题讨论】:

    标签: sql sql-server date


    【解决方案1】:

    您可以使用递归 CTE:

    with cte as (
          select marketid, deliverydate, deliverydate as date,
                 dateadd(day, -1, lead(deliverydate) over (partition by marketid order by deliverydate)) as lastdd
          from #market m
          union all
          select marketid, deliverydate, dateadd(day, 1, date) as date,
                 lastdd
          from cte
          where date < lastdd
         )
    select marketid, deliverydate, date
    from cte;
    

    如果您的间隔时间可以超过 100 天,那么您将需要 option (maxrecursion 0)

    【讨论】:

    • 感谢您的回复。如果我理解正确,我们首先创建下一个交货日期之前的日期,然后添加其间的所有日期?您能否编辑答案以帮助我理解 cte 的部分在这里,因为查询显示在 cte 内加入 cte。还有这里的 nextdd 是什么?
    • @AnishaSinghal 。 . . CTE 上没有“加入”。这就是答案。
    • 嗨,戈登,您能解释一下 nextdd 存储的价值吗?这是我唯一出错的地方。
    • @AnishaSinghal 。 . .代码有lastdd,这是当前交货日期/市场组合的最后日期。这是市场的下一个交货日期(如果有)减去一天。
    • 如果 nextdd 是下一个交货日期,那么解决方案应该是这样吗? lead([Delivery Date]) over (partition by DeliveryLocationID order by [Delivery date]) as nextdd 在 nextdd 列中
    【解决方案2】:

    假设间隔不超过 1000 天,以下应该可以工作

    with row_gen
      as (select top 1000 row_number() over(order by name)-1 as rnk
            from master..spt_values
         )
        ,dates
          as(
            select a.marketid,a.delivery_date,case when lead(a.delivery_date) over(partition by marketid order by delivery_date asc) is null then 
                                                        dateadd(day,1,a.delivery_date)
                                                   else lead(a.delivery_date) over(partition by marketid order by delivery_date asc) 
                                               end as next_val
              from dbo.t a
             )
    select *,dateadd(day,b.rnk,a.delivery_date)
      from dates a
      join row_gen b
        on dateadd(day,b.rnk,a.delivery_date)<a.next_val
    

    【讨论】:

      猜你喜欢
      • 2013-08-09
      • 1970-01-01
      • 2017-06-12
      • 1970-01-01
      • 2022-01-04
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多