如何获取包含2个已知日期之间的日期列表的列

时间:2014-09-18 11:05:41

标签: sql sql-server

我的表格看起来像这样

TicketNo     StartDate   EndDate     Price
TK001   01/04/2014  03/04/2014  3
TK002   02/04/2014  03/04/2014  2
TK003   30/04/2014  02/05/2014  10

我正在尝试编写一个包含4列的选择查询,其中有一个新列,其中包含StartDate和End Date之间的日期列表

像这样

TicketNo     StartDate   EndDate    DatesBetween     Price
TK001   01/04/2014  03/04/2014  01/04/2014  3
TK001   01/04/2014  03/04/2014  02/04/2014  3
TK001   01/04/2014  03/04/2014  03/04/2014  3
TK002   02/04/2014  03/04/2014  02/04/2014  2
TK002   02/04/2014  03/04/2014  03/04/2014  2
TK003   30/04/2014  02/05/2014  30/04/2014  10
TK003   30/04/2014  02/05/2014  01/05/2014  10
TK003   30/04/2014  02/05/2014  02/05/2014  10

最简单的方法是什么?

2 个答案:

答案 0 :(得分:1)

您可以使用sys.all_objectsROW_NUMBER()生成一个数字列表,并加入此表重复以下日期:

WITH N AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
            --CROSS JOIN sys.all_objects b
)
SELECT  T.TicketNo, 
        T.StartDate, 
        T.EndDate, 
        DatesBetween = DATEADD(DAY, N.Number, T.StartDate), 
        T.Price
FROM    T
        INNER JOIN N
            ON N.Number <= DATEDIFF(DAY, T.StartDate, T.EndDate);

如果这不能生成足够的行,那么只需在公用表表达式中取消注释交叉连接。

我真的会推荐a calendar table。它们非常有用,您的查询将是简单的; ified to:

SELECT  T.TicketNo, 
        T.StartDate, 
        T.EndDate, 
        DatesBetween = c.Date, 
        T.Price
FROM    T
        INNER JOIN dbo.Calendar AS c
            ON c.Date >= T.StartDate
            AND c.Date <= T.EndDate;

任务是否应该变得更复杂,例如只是在两个日期(包括公共假期)之间的工作日,然后初始查询变得复杂,但是使用日历表这是一个非常容易的变化。

答案 1 :(得分:1)

您可以使用递归CTE执行此操作:

with cte as (
      select t.TicketNo, t.StartDate, t.StartDate as DateBetween, t.EndDate, t.Price 
      from mytable t
      union all
      select cte.TicketNo, cte.StartDate, dateadd(day, 1, cte.DateBetween), cte.EndDate, cte.Price
      from cte
      where cte.DateBetween < cte.EndDate
)
select *
from CTE;