SQL-选择子查询中的最后一条记录,包括其他条件

时间:2018-09-20 05:35:44

标签: sql sql-server subquery

我们有一个门户,客户可以在此门户网站上提交认证,然后将其分配给各个培训师并由他们进行验证。我试图找出:

1)在过去的7天内,一位特定的培训师已验证了多少认证(已解决)

2)当前为培训员分配了多少个证书。

这是数据库结构的一部分:

dbo.Attempt  | dbo.AttemptHistory        | dbo.Person      | dbo.Trainer
Id     int   | Id            int         | Id      int     | Id        int
Score  int   | AttemptId     int         | Name    varchar | PersonId  int
             | StatusId      int         | Surname varchar | 
             | ChangeStamp   datetime    |                 |
             | PersonId      int         |                 |

当接收到尝试并分配了尝试时,将创建2条AttemptHistory记录(StatusIds 1和5)。验证后,将创建3rd AttemptHistory记录(状态ID 10)。

培训者由PersonId表示。

查找培训员已经过验证的尝试的次数很容易,因为经过验证的StatusId始终是Attempt生命周期中的最后一个。这是获取经过验证的尝试次数的脚本:

,(
    SELECT COUNT(Attempt.Id) 
    FROM Attempt

    INNER JOIN AttemptHistory ON AttemptHistory.AttemptId = Attempt.Id

    WHERE AttemptHistory.PersonId = Trainer.PersonId
    AND AttemptHistory.StatusId = 10 
    AND AttemptHistory.ChangeStamp >= Dateadd(Day, -7, getdate())

)                                               
AS AttemptsVerifiedFromTo

我的问题是,如何找出当前分配给特定教练的尝试次数?

查询AttemptHistory时,我需要找到一条记录:

1)属于当前尝试(AttemptId)

2)分配给特定的培训师(PersonId)

3)具有“已分配”状态(StatusId)

4)是属于当前尝试的最后一条记录(具有最高ID或最新的changeStamp)。换句话说-在此“已分配”历史记录之后,没有后续记录(例如,状态为“已验证”)。

我该如何实现?

编辑:这是我正在使用的整个脚本,从中可以看到所需的输出数据结构。

SELECT 
     Trainer.Id        AS TrainerId
    ,Trainer.PersonId  AS TrainerPersonId
    ,Person.Name       AS TrainerName
    ,Person.Surname    AS TrainerSurname    
    ,(
        SELECT COUNT(Attempt.Id) 
        FROM Attempt

        INNER JOIN AttemptHistory ON AttemptHistory.AttemptId = Attempt.Id

        WHERE AttemptHistory.PersonId = Trainer.PersonId
        AND AttemptHistory.StatusId = 10 
        AND AttemptHistory.ChangeStamp >= Dateadd(Day, -7, getdate())

    )                                               
    AS AttemptsVerifiedFromTo

    ,(  /* THIS IS JUST A TEST I TRIED TO GET THE NUMBER OF ASSIGNED ATTEMPTS */
        SELECT COUNT(Attempt.Id) 
        FROM Attempt

        INNER JOIN AttemptHistory ON AttemptHistory.AttemptId = Attempt.Id

        WHERE AttemptHistory.PersonId = Trainer.PersonId
        AND AttemptHistory.StatusId = 5
        AND Attempt.Reply IS NULL
        AND AttemptHistory.Id = (
            SELECT TOP 1 (AttemptHistory.Id) FROM AttemptHistory
            INNER JOIN Attempt ON AttemptHistory.AttemptId = Attempt.Id
        )
   )                                                
   AS AttemptsAssigned      


FROM Trainer
INNER JOIN Person ON Person.Id = Trainer.PersonId

0 个答案:

没有答案