获得相同Id的第二个发布日期

时间:2014-08-10 21:16:18

标签: sql sql-server

我有两张桌子

表1

Employee ID     HireDate 
1               2009-09-01
2               2009-09-04
1               2009-08-04

表2:

Employee ID     EndDate
1               2009-09-01
1               2009-08-04

表3 :(我从查询中得到的结果)

Employee ID     EndDate
1               2009-09-01
1               2009-09-01

我希望表2中的Indate列可以从表1中HireDate值中为每个员工更新。条件是

  1. 当员工ID第一次出现在表2中时,我应该获得与该员工ID相对应的最早的Indate。
  2. 如果再次出现相同的员工ID,我应该得到第二个最早的日期。
  3. 我正在使用的查询..

    UPDATE Test.dbo.Table1
        SET EndDate  = b.MinBDate
    FROM Test.dbo.Table1  a
    OUTER APPLY
    (    
        SELECT MIN(b.HireDate) MinBDate
        FROM Test.dbo.Table2 b
        WHERE a.EmployeeID = b.EmployeeID
    ) b
    

1 个答案:

答案 0 :(得分:1)

您的查询是最早的日期,而不是第二个最早的日期。此外,update语句指的是错误的表。它需要使用from子句中定义的别名。所以你的查询应该更像是:

UPDATE a
    SET EndDate  = b.MinBDate
FROM Test.dbo.Table1 a OUTER APPLY
     (SELECT TOP 1 b.HireDate as MinBDate
      FROM Test.dbo.Table2 b
      WHERE a.EmployeeID = b.EmployeeID
      ORDER BY b.HireDate
     ) b;

第二个最早的日期:

UPDATE a
    SET EndDate = b.HireDate
FROM Test.dbo.Table1 a OUTER APPLY
     (SELECT TOP 1 HireDate
      FROM (SELECT TOP 2 b.HireDate as HireDate
            FROM Test.dbo.Table2 b
            WHERE a.EmployeeID = b.EmployeeID
            ORDER BY b.HireDate ASC
           ) b
      ORDER BY HireDate DESC
     ) b

您也可以使用row_number()编写逻辑,这更有可能是我这样做的。但是,您从outer apply开始,所以我保留了这种结构。

编辑:

我会把它写成:

UPDATE a
    SET EndDate = b.HireDate
FROM Test.dbo.Table1 a join
     (SELECT b.HireDate as HireDate,
             row_number() over (partition by b.EmployeeId order by HireDate) as seqnum
      FROM Test.dbo.Table2 b
     ) b
     ON a.EmployeeID = b.EmployeeID and seqnum = 2;

outer apply可能有更好的表现。我更喜欢这种方法,因为它适用于更多的数据库。