SQL 获取每组最大值的记录

SQL Get records with max value for each group

我有 2 tables 期刊和用户 日志看起来像这样:

TransTime RegNumber UserID
5/26/2022 11:00:00 101 3
5/26/2022 11:30:00 102 2
5/26/2022 13:00:00 101 5
5/26/2022 14:30:00 103 4
5/26/2022 15:00:00 102 1

用户table

UserID Name
1 Ross
2 Rachel
3 Chandler
4 Monica
5 Joey

我想做的是获得 table 的登记册及其最近的用户名。这看起来应该很简单。但是由于我在用户 ID 上加入 tables,所以我在第一个 table 上获得了所有 5 条记录。但它应该是这样的:

RegNumber LastUser
101 Joey
102 Ross
103 Monica

我尝试了多种解决方案,但没有找到合适的解决方案。感谢任何帮助。

如果您从每个 regNumber 的最大传输时间的内部连接开始,然后与用户 table:

连接
Select J.RegNumber, U.Name
From Journal J
Inner join 
(Select Max(TransTime) as TransTime, RegNumber 
From Journal
Group by RegNumber) J2 on J.TransTime = J2.TransTime and J.RegNumber = J2.RegNumber
Inner join
Users U on J.UserID = U.UserID
select u.Name, j.* 
from journal j 
inner join ( 
    select max(TransTime) last_update, RegNumber 
    from journal 
    group by RegNumber 
) t1 
inner join j.RegNumber = t1.RegNumber 
   and t1.last_update = j.TransTime 
left join Users_Journal uj on j.UserID= uj.UserID

这是一个使用 CTE 的选项:

;with cte as
(
    Select  RegNumber,
            UserID = max(UserID)
    From journal
    group by RegNumber
)
Select  RegNumber = C.RegNumber,
        LastUser = U.Name
From cte C
Join users U ON U.Userid = C.UserID
order by C.RegNumber

从本质上讲,这个答案与其他答案没有本质区别。但是,就对目标受众的帮助而言,它更具可读性,更 self-documenting,并且在格式方面更标准。

侧边栏:此 SQL 将数据设计作为给定的表面价值,并隐含假设 TransTime 是 PK 或至少唯一索引,可能与 RegNumber 结合使用。最重要的是,最好有更多关于密钥结构的信息以及原始问题。

WITH LatestEntries AS
(
    SELECT
        MAX(TransTime) AS LatestTimeForReg
        ,RegNumber
    FROM
        Journal
    GROUP BY
        RegNumber
)
SELECT
    J.RegNumber
    ,U.[Name] AS LastUser
FROM
    LatestEntries LE
    INNER JOIN Journal J ON LE.LatestTimeForReg = J.TransTime AND LE.RegNumber = J.RegNumber
    INNER JOIN Users U ON J.UserID = U.UserID
ORDER BY
    J.RegNumber
;

您可以使用 temptablecte 结构根据 RegNo 和 Trantime 对您的数据进行排名,如下所示,然后检索每个期刊的最新用户:

CREATE TABLE #Journals (TranTime DATETIME, RegNo INT, UserId INT)
CREATE TABLE #Users (UserId INT, UserName NVARCHAR(100))

INSERT INTO #Users VALUES(1,'Ross'),(2,'Rachel'),(3,'Chandler'),(4,'Monica'),(5,'Joey')

INSERT INTO #Journals VALUES ('5/26/2022 11:00:00',101,3),('5/26/2022 11:30:00',102,2),
('5/26/2022 13:00:00',101,5),('5/26/2022 14:00:00',103,4),('5/26/2022 15:00:00',102,1)
    
;WITH cte as (
        SELECT *,rn=ROW_NUMBER() OVER (PARTITION BY RegNo ORDER BY TranTime DESC)
        FROM #Journals
    )
SELECT RegNo, u.UserName
FROM cte
INNER JOIN #Users u ON u.UserId = cte.UserId
WHERE rn=1 --since sort by TranTime is descending, it'll give you the latest user for each specific RegNo
ORDER BY RegNo

已测试,可在 SQL Server 2016 上运行。