【问题标题】:Split row based on start end date SQL Server根据开始结束日期 SQL Server 拆分行
【发布时间】:2015-04-06 17:30:41
【问题描述】:

假设我在表格中有这些值

Package | Start Date | End date 
---------------------------------
PKG123  | 01-02-2013 | 31-01-2016
PKG456  | 15-06-2010 | 14-06-2014

我想写一个 select 语句,它应该给我这样的结果:

Package | Start Date | End date
-----------------------------------
PKG123  | 01-02-2013 | 31-01-2014
PKG123  | 01-02-2014 | 31-01-2015
PKG123  | 01-02-2015 | 31-01-2016
PKG456  | 15-06-2010 | 14-06-2011
PKG456  | 15-06-2011 | 14-06-2012
PKG456  | 15-06-2012 | 14-06-2013
PKG456  | 15-06-2013 | 14-06-2014

有没有办法在 TSQL 中做到这一点?

请注意,我不是在寻找两个日期之间的完整日期列表,而是在寻找基于 12 个月的持续时间将一行拆分为多行。

我使用的是 SQL Server 2008 R2。

【问题讨论】:

  • 行数多吗?我假设您可以使用递归 CTE 执行此操作,但如果要生成的行数和年数很大,则可能会导致性能问题。
  • @JamesZ 该表大约有 9500 行,从 2010 年至今可能涉及的年数 - 会随着时间的推移而增加。

标签: sql-server sql-server-2008-r2


【解决方案1】:

这是使用递归 CTE 的方法:

;with CTE as (
  select package, startDate, EndDate from data
  union all
  select package, dateadd(month, 12, startDate), EndDate
  from CTE where EndDate > dateadd(month, 12, startDate)
)

select 
  package,
  startdate,
  case when enddate <= dateadd(month, 12, startdate)
    then enddate else dateadd(day, -1, dateadd(month, 12, startdate)) end
    as enddate
From
  CTE 
order by package, startdate

CTE 将从表中取出行,然后如果开始日期 + 12 个月小于结束日期,则递归选择新行。 CTE 之外的选择将确定要使用的行中的哪个值,开始日期 + 12 个月或结束日期。

SQL 小提琴:http://sqlfiddle.com/#!6/5bfbf/4

【讨论】: