【问题标题】:historic 'slice' of table具有历史意义的“切片”表
【发布时间】:2016-01-25 01:09:01
【问题描述】:

SQL Server 女士。

我有一张表格,用于监控学生学校的申请状态。 学生可以申请多所学校,每所学校都可以接受/拒绝/候补学生。

tblApplicantSchools 看起来像这样:

ApplicantID    |    SchoolID     |     StatusID

独特的申请人可以出现在这里申请多所学校 - 但每个学校申请只有一个身份。

我还有一张历史表 tblApplicantSchools_shadow,它反映了对 tblApplicantSchools 所做的任何更改。它与上面的相同,除了它还保存了更改的时间,以及是否是对原始表的插入/更新/删除。 因此,在他的shadow 表中,可能有多个学生,到多个具有多种状态的学校(当他们通过这个过程时)。

我想做的是将shadow 表切到某个日期,并将每个申请的最新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 的最新更新。

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

谢谢

【问题讨论】:

    标签: sql sql-server tsql distinct


    【解决方案1】:

    你可以使用窗口函数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 平局的可能性很低。

    【讨论】:

    • 这绝对是我想学的东西,谢谢。看起来它非常强大。现在太多太多了,我正在寻求其他更标准的解决方案。
    【解决方案2】:

    如果您更喜欢 ANSI-92 兼容的解决方案,或者您害怕窗口函数,那么这个查询可能会很有用:

    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
    

    【讨论】:

      猜你喜欢
      • 2012-02-24
      • 1970-01-01
      • 1970-01-01
      • 2018-10-20
      • 2018-03-06
      • 1970-01-01
      • 2020-07-02
      • 2019-02-06
      • 2023-03-17
      相关资源
      最近更新 更多