table 的历史记录 'slice'

historic 'slice' of table

女士SQL服务器。

我有一个 table 可以监控学生学校的申请状态。 学生可以申请多所学校,每所学校都可以 accept/reject/waitlist 学生。

Table tblApplicantSchools 看起来像这样:

ApplicantID    |    SchoolID     |     StatusID

此处可以出现独特的申请人申请多所学校 - 但每个学校申请只能有一个状态。

我还有一个历史性的 table tblApplicantSchools_shadow,它会影响对 tblApplicantSchools 所做的任何更改。它与上面的相同,只是它还保存了进行更改的时间,以及它是否是原始 table 上的 insert/update/delete。 因此,在他 shadow table 中,可能有多个学生,到具有多个状态的多个学校(因为他们在整个过程中移动)。

我想做的是,将 shadow table 切片到某个日期,然后将每个应用程序的最近 statusID 带到每个学校申请人。这有意义吗? 例如:

ApplicantID    |    SchoolID     |     StatusID       |    ChangeDate
-----------------------------------------------------------------------
    11                   2                 3                  22/1/2015
    11                   2                 4                  30/1/2015
    11                   3                 4                  25/1/2015
    11                   3                 6                  29/1/2015

所以我只想看到上面的第 2 行和第 4 行,因为它们是每所学校的申请人 #11 的最新更新。

有人可以指导我如何做到这一点吗?我的设置有点复杂,但我认为这个例子简化了它,所以问题很清楚。

谢谢

你可以使用窗口函数ROW_NUMBER:

SELECT *
FROM (SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY ApplicantID,SchoolID  
                                       ORDER BY ChangeDate DESC)
      FROM tblApplicantSchools_shadow) AS sub
WHERE rn = 1;

LiveDemo

输出:

╔═════════════╦══════════╦══════════╦═════════════════════╗
║ ApplicantID ║ SchoolID ║ StatusID ║     ChangeDate      ║
╠═════════════╬══════════╬══════════╬═════════════════════╣
║          11 ║        2 ║        4 ║ 2015-01-30 00:00:00 ║
║          11 ║        3 ║        6 ║ 2015-01-29 00:00:00 ║
╚═════════════╩══════════╩══════════╩═════════════════════╝

请记住,如果ChangeDate只是DATE(没有时间标准,有可能平手,你应该用RANK()代替。有DATETIME的概率平局率低。

如果您更喜欢符合 ANSI-92 的解决方案,或者如果您害怕 window 函数,那么此查询可能会有用:

SELECT s1.ApplicantID, s1.SchoolID, s1.StatusID, s1.ChangeDate
FROM shadow s1
INNER JOIN
(
    SELECT ApplicantID, SchoolID, MAX(ChangeDate) AS maxDate
    FROM shadow
    GROUP BY ApplicantID, SchoolID
) s2
ON s1.ApplicantID = s2.ApplicantID AND s1.SchoolID = s2.SchoolID
    AND s1.ChangeDate = s2.maxDate