我的表格看起来像这样
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
最简单的方法是什么?
答案 0 :(得分:1)
您可以使用sys.all_objects
和ROW_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;