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
;
您可以使用 temptable
或 cte
结构根据 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 上运行。
我有 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
;
您可以使用 temptable
或 cte
结构根据 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 上运行。