在SQL Server的每一行中添加15天

时间:2014-08-22 19:24:14

标签: sql-server sql-server-2008

我有如下所示的数据(当前数据)

  • ID列不是主键
  • 要求为开始日期添加15天

e.g。

  • 第一行 - 添加15天startdate - 输出1/30/13
  • 第二行 - 从第一行添加15天到新日期1/30/13 - 输出2/14/14
  • 第三行 - 从第二行添加15天到新日期 - 输出3/1/13

修改了NewDate列显示 - 我们是否可以按照所需输出数据集的要求显示Newdate列?

当前数据

ID           NAME       START         END         TRAVELDATE      
===============================================================
1            TOM        1/15/13       12/6/13     1/25/13         
1            TOM        1/15/13       12/6/13     2/2/13          
1            TOM        1/15/13       12/6/13     3/1/13   

期望的输出

ID           NAME       START         END         TRAVELDATE      NEWDATE
========================================================================
1            TOM        1/15/13       12/6/13     1/25/13         1/15/13 - 1/30/13
1            TOM        1/15/13       12/6/13     2/2/13          1/30/13 - 2/14/13
1            TOM        1/15/13       12/6/13     3/1/13          2/14/13 - 3/1/13

4 个答案:

答案 0 :(得分:2)

您可以使用ROW_NUMBER()功能和DATEADD()

执行此操作
SELECT *,DATEADD(day,ROW_NUMBER()OVER(ORDER BY TravelDate)*15,Start) NewDate
FROM Table1

演示:SQL Fiddle

如果您的示例不全面,可能需要进行调整,即如果Start日期实际上可以更改,那么您希望将第一个Start值加载到变量中并将其用于DATEADD()函数,而不是引用每行的Start值。

答案 1 :(得分:1)

制作一些测试数据:

DECLARE @Travel TABLE
(
    ID INT,
    NAME VARCHAR(20),       
    STARTDT DATE,         
    ENDDT DATE,         
    TRAVELDATE DATE
)

INSERT INTO @Travel
VALUES
(1, 'TOM', '1/15/13', '12/6/13', '1/25/13'),         
(1, 'TOM', '1/15/13', '12/6/13', '2/2/13'),          
(1, 'TOM', '1/15/13', '12/6/13', '3/1/13');

现在我们使用行号来确​​定我们的序列,然后对每条记录使用序列* 15天:

SELECT *,
    DATEADD(DAY, 15 * RN, STARTDT) NEWDATE
FROM
(
    SELECT *,
        ROW_NUMBER() OVER (ORDER BY TravelDate) RN
    FROM @Travel
) d

这是输出:

ID  NAME    STARTDT ENDDT   TRAVELDATE  RN  NEWDATE
1   TOM 2013-01-15  2013-12-06  2013-01-25  1   2013-01-30
1   TOM 2013-01-15  2013-12-06  2013-02-02  2   2013-02-14
1   TOM 2013-01-15  2013-12-06  2013-03-01  3   2013-03-01

以下是所要求的更新版本:

SELECT *,
    DATEADD(DAY, 15 * (RN - 1), STARTDT) STARTNEWDATE,
    DATEADD(DAY, 15 * RN, STARTDT) ENDNEWDATE
FROM
(
    SELECT *,
        ROW_NUMBER() OVER (ORDER BY TravelDate) RN
    FROM @Travel
) d

以下是修改后的输出:

ID  NAME    STARTDT ENDDT   TRAVELDATE  RN  STARTNEWDATE    ENDNEWDATE
1   TOM 2013-01-15  2013-12-06  2013-01-25  1   2013-01-15  2013-01-30
1   TOM 2013-01-15  2013-12-06  2013-02-02  2   2013-01-30  2013-02-14
1   TOM 2013-01-15  2013-12-06  2013-03-01  3   2013-02-14  2013-03-01

答案 2 :(得分:0)

这听起来像是递归CTE的一个很好的候选者。

WITH c AS (

SELECT T.ID, NewDate
FROM #Test T

UNION ALL 

SELECT T.ID, DATEADD(DAY, 15, c.NewDate)
FROM #Test T
JOIN c ON c.id =  T.id
WHERE DATEADD(DAY, 15, c.NewDate) < '2015-12-31'

)

SELECT * FROM  c 

答案 3 :(得分:0)

我想你想要这样的东西

SELECT ID,NAME,START,[END],TRAVELDATE
, ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY TRAVELDATE) as rowNo
, DATEADD(DAY,15,START) as newDate
INTO #TEMP
FROM START


;WITH c AS(
SELECT ID,NAME,START,[END],TRAVELDATE, NEWDATE, rowNo
FROM #TEMP T
where T.rowNo = 1
UNION ALL
    SELECT t.ID,t.NAME,t.START,t.[END],t.TRAVELDATE, DATEADD(DAY,15,c.NEWDATE) as newDate, t.rowNo
    FROM #TEMP T
    JOIN c ON T.rowNo = c.rowNo+1
    AND T.NAME = c.NAME

)
SELECT * FROM c
ORDER BY c.NAME, c.rowNo

如果您有多个名称并且想要从每个名称的开始日期开始,这种方法很有效。

有关详细信息,请参阅Sql Fiddle