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;
输出:
╔═════════════╦══════════╦══════════╦═════════════════════╗
║ 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
女士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;
输出:
╔═════════════╦══════════╦══════════╦═════════════════════╗
║ 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