在SQL中创建用于迭代的行

时间:2019-01-08 16:19:05

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

我必须创建一个报告,说明该票在每个月的第一天都打开了多长时间,另一个报告显示了关闭票用了多长时间。在不创建每个月间隔的情况下,使用SQL执行此操作的最佳方法是什么?我正在使用SQL Server 2008 R2

我当前的数据:

| Ticket | Start Date | End Date   |
|--------|------------|------------|
| ABC    | 5/8/2018   | 9/28/2018  |
| XYZ    | 6/22/2018  | 10/15/2018 |

预期结果:

| Ticket | Start Date | End Date   | Report Date | Ticket Age | Ticket Interval |
|--------|------------|------------|-------------|------------|-----------------|
| ABC    | 5/8/2018   | 9/28/2018  | 6/1/2018    | 24         |                 |
| ABC    | 5/8/2018   | 9/28/2018  | 7/1/2018    | 54         |                 |
| ABC    | 5/8/2018   | 9/28/2018  | 8/1/2018    | 85         |                 |
| ABC    | 5/8/2018   | 9/28/2018  | 9/1/2018    | 116        |                 |
| ABC    | 5/8/2018   | 9/28/2018  | 10/1/2018   |            | 143             |
| XYZ    | 6/22/2018  | 10/15/2018 | 7/1/2018    | 9          |                 |
| XYZ    | 6/22/2018  | 10/15/2018 | 8/1/2018    | 40         |                 |
| XYZ    | 6/22/2018  | 10/15/2018 | 9/1/2018    | 71         |                 |
| XYZ    | 6/22/2018  | 10/15/2018 | 10/1/2018   | 101        |                 |
| XYZ    | 6/22/2018  | 10/15/2018 | 11/1/2018   |            | 115             |

1 个答案:

答案 0 :(得分:4)

您可以使用递归CTE:

with cte as (
      select ticket, sdate, edate, dateadd(month, 1, dateadd(day, 1 - day(sdate), sdate)) as reportdate
      from t
      union all
      select ticket, sdate, edate, dateadd(month, 1, reportdate)
      from cte
      where reportdate <= edate
     )
select cte.*, datediff(day, sdate, reportdate) as ticketage,
       (case when datediff(month, edate, reportdate) = 1 then datediff(day, sdate, edate) end) as interval
from cte
order by ticket, reportdate;

我包括了机票上个月的机票年龄。如果您确实不想要它,可以使用类似的case表达式。

Here是db <>小提琴。