Sql server 日期序列的持续时间-sql server

Sql server 日期序列的持续时间-sql server,sql-server,Sql Server,使用SQL Server 2012。每天晚上,一个数据仓库负载填充一个贷款通过的里程碑日期表。数据如下所示: CREATE TABLE TestData (LoanKey int, MilestoneCompletedDate datetime, Duration int) INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-10-16 16:51:56.000') INSERT TestData (LoanKe

使用SQL Server 2012。每天晚上,一个数据仓库负载填充一个贷款通过的里程碑日期表。数据如下所示:

CREATE TABLE TestData (LoanKey int, MilestoneCompletedDate datetime, Duration int)

INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-10-16 16:51:56.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-10-18 15:11:29.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-10-23 16:21:59.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-10-28 14:52:00.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-08-26 10:53:37.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-09-19 15:16:38.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-09-20 08:31:38.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-10-08 15:56:05.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-10-16 16:11:10.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-10-09 11:20:35.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (2, '2013-09-10 11:15:09.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-06-03 16:22:32.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-06-21 14:46:24.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-08-30 10:03:08.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-08-30 13:55:17.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-09-03 15:28:22.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-09-04 09:30:08.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-09-12 10:44:46.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-09-25 16:06:43.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-06-24 11:59:25.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-09-25 16:06:43.000')
INSERT TestData (LoanKey, MilestoneCompletedDate) VALUES (42, '2013-01-17 15:06:14.000')
加载数据后,我想更新“持续时间”字段。下面是一些伪代码:

UPDATE TestData SET Duration = 'Find the DateDiff between the current rows MilestoneCompletedDate and the next greatest milestone completion date for the same loan' 
我可以生成一个带有分区依据和排序依据的行号:

SELECT 
    LoanKey,
    MilestoneCompletedDate, 
    ROW_NUMBER() OVER (PARTITION BY LoanKey ORDER BY MilestoneCompletedDate DESC) AS SequenceNumber
FROM 
    [dbo].[TestData] 
有没有关于从这里到哪里的想法


谢谢你的关注

这应该可以完成这项工作,将
HOUR
更改为您喜欢的任何单位:

UPDATE a
SET Duration = DATEDIFF( HOUR 
                        ,(SELECT MAX(b.MilestoneCompletedDate) 
                          FROM TestData b
                          WHERE b.MilestoneCompletedDate < a.MilestoneCompletedDate
                            AND b.LoanKey = a.LoanKey) 
                        ,a.MilestoneCompletedDate )
FROM TestData a
WHERE Duration IS NULL
或者,您可以像您所想的那样使用
行号
,但这有点混乱。比如:

;WITH cte AS (
    SELECT 
        LoanKey,
        MilestoneCompletedDate, 
        Duration,
        ROW_NUMBER() OVER (PARTITION BY LoanKey 
                           ORDER BY MilestoneCompletedDate ASC) AS SeqNum
    FROM @TestData
    WHERE duration IS NULL
)
UPDATE a
SET Duration = DATEDIFF(HOUR
                       ,b.MilestoneCompletedDate
                       ,a.MilestoneCompletedDate)
FROM cte a
INNER JOIN cte b ON a.LoanKey = b.LoanKey 
                AND a.SeqNum = b.SeqNum + 1

返回相同的结果集。

由于您使用的是SQL Server 2012,因此可以使用:

从同一结果集中的后续行访问数据,而无需在SQL Server 2012中使用自联接
LEAD
提供对位于当前行之后的给定物理偏移处的行的访问

产生:

LoanKey     MilestoneCompletedDate  Duration
----------- ----------------------- -----------
2           2013-10-16 16:51:56.000 166773
2           2013-10-18 15:11:29.000 436230
2           2013-10-23 16:21:59.000 426601
2           2013-10-28 14:52:00.000 NULL
2           2013-08-26 10:53:37.000 1297292
2           2013-09-19 15:16:38.000 62100
2           2013-09-20 08:31:38.000 1581867
2           2013-10-08 15:56:05.000 69870
2           2013-10-16 16:11:10.000 2446
2           2013-10-09 11:20:35.000 622235
2           2013-09-10 11:15:09.000 792089
42          2013-06-03 16:22:32.000 1549432
42          2013-06-21 14:46:24.000 249181
42          2013-08-30 10:03:08.000 13929
42          2013-08-30 13:55:17.000 351185
42          2013-09-03 15:28:22.000 64906
42          2013-09-04 09:30:08.000 695678
42          2013-09-12 10:44:46.000 1142517
42          2013-09-25 16:06:43.000 0
42          2013-06-24 11:59:25.000 5781823
42          2013-09-25 16:06:43.000 NULL
42          2013-01-17 15:06:14.000 11841378

在以前版本的SQL Server上,我会执行基于
行号()的查询,并执行
LEAD
文档中提到的自连接操作:

;With Ordered as (
    SELECT 
        LoanKey,
        MilestoneCompletedDate, 
        ROW_NUMBER() OVER (PARTITION BY LoanKey
                ORDER BY MilestoneCompletedDate DESC) AS SequenceNumber
    FROM 
        [dbo].[TestData]
)
UPDATE o1 SET Duration =
    DATEDIFF(second,o1.MilestoneCompletedDate,o2.MilestoneCompletedDate)
FROM Ordered o1
LEFT JOIN Ordered o2
ON o1.LoanKey = o2.LoanKey and o1.SequenceNumber = o2.SequenceNumber - 1

答得好,我完全忘记了2008年后的功能,
LEAD
是一个很棒的功能。感谢您的回复!领导方法存在问题。LoanKey=2和MilestoneCompletedDate=2013-10-28定义的行的持续时间为NULL。这是贷款的最后一个里程碑日期。上一个里程碑是2013年10月23日,因此持续时间应为5天。看起来正确的持续时间都向下移动了一个里程碑。第二种方法是将Duration添加到有序表中,并在DATEDIFF中反转02和01。@jjm-这是因为您谈到了获取一行,然后查找下一个最大的行,所以我假设您希望根据下一个日期更新当前行。但是从您的评论来看,您想要的(对于任何特定行)是查找前一行。在这种情况下,要么将
LAG
替换为
LEAD
,要么(逻辑上相同)将
顺序更改为
ASC
,而不是
DESC
。我明白了。。。很酷。我不知道滞后和超前!这就是我想要的!非常感谢。行号是否实际计算两次取决于优化器,我甚至不会在执行计划中发现,除非存在性能问题。公平竞争,删除。在过去链接CTE时,通过尽可能少地从每个CTE中进行选择,我看到了显著的性能提升,但我意识到没有一般规则。您的第一种方法适合我,我喜欢它的简单性。非常感谢你!没问题,尽管看起来Damien有一个简单的解决方案来解决你在铅方面遇到的问题
LoanKey     MilestoneCompletedDate  Duration
----------- ----------------------- -----------
2           2013-10-16 16:51:56.000 166773
2           2013-10-18 15:11:29.000 436230
2           2013-10-23 16:21:59.000 426601
2           2013-10-28 14:52:00.000 NULL
2           2013-08-26 10:53:37.000 1297292
2           2013-09-19 15:16:38.000 62100
2           2013-09-20 08:31:38.000 1581867
2           2013-10-08 15:56:05.000 69870
2           2013-10-16 16:11:10.000 2446
2           2013-10-09 11:20:35.000 622235
2           2013-09-10 11:15:09.000 792089
42          2013-06-03 16:22:32.000 1549432
42          2013-06-21 14:46:24.000 249181
42          2013-08-30 10:03:08.000 13929
42          2013-08-30 13:55:17.000 351185
42          2013-09-03 15:28:22.000 64906
42          2013-09-04 09:30:08.000 695678
42          2013-09-12 10:44:46.000 1142517
42          2013-09-25 16:06:43.000 0
42          2013-06-24 11:59:25.000 5781823
42          2013-09-25 16:06:43.000 NULL
42          2013-01-17 15:06:14.000 11841378
;With Ordered as (
    SELECT 
        LoanKey,
        MilestoneCompletedDate, 
        ROW_NUMBER() OVER (PARTITION BY LoanKey
                ORDER BY MilestoneCompletedDate DESC) AS SequenceNumber
    FROM 
        [dbo].[TestData]
)
UPDATE o1 SET Duration =
    DATEDIFF(second,o1.MilestoneCompletedDate,o2.MilestoneCompletedDate)
FROM Ordered o1
LEFT JOIN Ordered o2
ON o1.LoanKey = o2.LoanKey and o1.SequenceNumber = o2.SequenceNumber - 1