迭代行以捕获下一行中的值

时间:2013-10-23 16:22:05

标签: sql sql-server-2008 iteration

我一直是这个论坛的长期读者。它给了我很多帮助,但是我有一个问题,我无法找到特定于我的要求的解决方案。

我的任务是制定一个指标,以确定“员工绩效评估”过期的天数。数据采用以下格式:

EmployeeID LastEvalCompleteDate NextEvalDueDate
1001       2010-01-01           2010-11-01
1001       2010-11-20           2011-11-01
1001       2011-10-29           2012-11-15
1002       NULL                 2013-12-01

根据上述示例数据,员工 1001 自2010-01-01以来已经有3次逃亡。员工 1002 已于今年开始,他的第一个评估将于2013-12-01完成。

我需要做的是将数据转换为这种格式:

EmployeeID EvalDueDate EvalCompleteDate DaysPastDue
1001       2010-11-01  2010-11-20       19
1001       2011-11-01  2011-10-29       -2
1001       2012-11-15  NULL             342 (based on today's date)
1002       2013-12-01  NULL             -39 (based on today's date)

正如您所注意到的,我通过获取NextEvalDueDate列的值并将其映射到新表中的EvalDueDate列来派生新行。我还会将 NEXT行中的LastEvalCompleteDate列中的值设为值,并将其映射到NextEvalDueDate列。

我在迭代给定EmployeeID的行时遇到问题。我尝试使用ROW_NUMBER() OVER (PARTITION BY ...),但它并没有把我带到任何地方。

我感谢任何帮助。谢谢。

2 个答案:

答案 0 :(得分:1)

您使用ROW_NUMBER() OVER (PARTITION BY ...)进入了正确的方向。不知道你在哪里卡住了,但它应该是这样的:

WITH CTE AS 
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY NextEvalDueDate) RN
    FROM dbo.Table1
)
SELECT 
    c1.EmployeeID
  , c1.NextEvalDueDate AS EvalDueDate
  , c2.LastEvalCompleteDate AS EvalCompleteDate 
  , DATEDIFF(DAY, c1.NextEvalDueDate, COALESCE(c2.LastEvalCompleteDate, GETDATE())) AS DaysPastDue
FROM CTE c1
LEFT JOIN CTE c2 ON c1.EmployeeID = c2.EmployeeID AND c1.RN = c2.RN - 1
ORDER BY c1.EmployeeID, c1.RN

答案 1 :(得分:0)

DECLARE @Results TABLE
(
    EmployeeID INT NOT NULL,    
    RowNum INT NOT NULL,        
        PRIMARY KEY (RowNum, EmployeeID),
    LastEvalCompleteDate DATE,
    NextEvalDueDate DATE
);
INSERT  @Results (RowNum, EmployeeID, LastEvalCompleteDate, NextEvalDueDate)
SELECT  ROW_NUMBER() OVER(PARTITION BY e.EmployeeID ORDER BY e.LastEvalCompleteDate),
        e.EmployeeID,
        e.LastEvalCompleteDate,
        e.NextEvalDueDate
FROM    dbo.EmployeeEvaluation e;

WITH Base
AS
(
SELECT  crt.RowNum,
        crt.EmployeeID,
        crt.NextEvalDueDate AS EvalDueDate,
        nxt.LastEvalCompleteDate AS EvalCompleteDate 
FROM    @Results crt
LEFT JOIN @Results nxt ON crt.EmployeeID = nxt.EmployeeID AND crt.RowNum + 1 = nxt.RowNum
)
SELECT  r.*,
        DATEDIFF(DAY, r.EvalDueDate, ISNULL(r.EvalCompleteDate, GETDATE())) AS DaysPastDue
FROM    Base r
ORDER BY r.EmployeeID, r.RowNum