在做SQL Server的同时做

时间:2017-07-17 02:26:03

标签: sql sql-server

我只是创建一个计划项目并需要帮助..

我有一个日程安排数据

ID      Programme        Start      End         Division
----------------------------------------------------------
M001    Math             1/1/2017   20/01/2017  Math
M002    Aljabar          2/2/2017   20/02/2017  Math
E001    Conversation     3/1/2017   25/01/2017  English
E002    Vocabs           3/1/2017   20/02/2017  English

我需要让它看起来像这样:

ID        Date     
------------------
M001     1/1/2017
M001     2/1/2017
M001     3/1/2017
so on until 20/1/2017
M002     2/2/2017
M002     3/2/2017
so on until 20/02/2017
E001     3/1/2017
E001     4/1/2017
so on until 25/01/2017
E002     3/1/2017
E002     4/1/2017
so on until 20/02/2017

由于

2 个答案:

答案 0 :(得分:3)

执行此操作的一种方法是使用递归CTE:

with cte as (
      select id, start as dte, end
      from t
      union all
      select id, dateadd(day, 1, dte), end
      from t
      where dte < end
     )
select id, dte
from cte
order by id, dte;

如果您有超过100天的时间,则需要使用MAXRECURSION选项。

注意:上面保留了问题中指定的列,假设这些列不是真实姓名。显然,end是保留字(并且start可能是将来的一个),因此如果它们是实际的列名,则应对其进行转义。

答案 1 :(得分:1)

您需要一个日历表来执行此操作。我宁愿在我的数据库中创建一个物理日历表,并在这种情况下使用它。以下是使用计数表方法动态生成日期的一种方法

DECLARE @minDate DATETIME

SELECT @minDate = Min([Start])
FROM   Yourtable

;WITH lv0 AS (SELECT 0 g UNION ALL SELECT 0)
    ,lv1 AS (SELECT 0 g FROM lv0 a CROSS JOIN lv0 b) -- 4
    ,lv2 AS (SELECT 0 g FROM lv1 a CROSS JOIN lv1 b) -- 16
    ,lv3 AS (SELECT 0 g FROM lv2 a CROSS JOIN lv2 b) -- 256
    ,lv4 AS (SELECT 0 g FROM lv3 a CROSS JOIN lv3 b) -- 65,536
    ,Tally (n) AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM lv3)
SELECT ID,
       Dateadd(DD, n - 1, @minDate)
FROM   Tally t
       JOIN Yourtable a
         ON Dateadd(DD, t.n - 1, @minDate) BETWEEN [Start] AND [End]
ORDER  BY ID,n; 

如果您想了解有关计数表的更多信息,请查看此链接Tally Tables in T-SQL