这似乎是一个重复的问题,但我在SO上找到的所有答案都没有帮助我解决这个问题。
所以,我有这个数据库存储项目的每个更新。基本上,首次创建项目时,statusId
为1,并且创建日期。如果有人更新了该项目并更改了该项目的状态,则会添加该项目的statusId
。例如。使用当前日期添加statusId
2的新行。等等等等。该表的一个示例如下所示:
id statusId updatedDate userId authId
1 1 2016-12-20 15:43:17.703 14 14
2 1 2016-12-20 15:54:01.523 14 15
3 2 2016-12-21 16:05:48.157 14 14
4 3 2016-12-21 16:27:58.610 14 15
5 1 2016-12-20 17:16:47.627 14 18
6 1 2016-12-20 17:27:58.930 14 19
7 1 2017-01-18 14:13:35.800 18 20
所以,我接下来要做的是查询给出最新statusId
的表格。对于上表,statusid
= 1的查询应显示以下结果:
id statusId updatedDate userId authId
5 1 2016-12-20 17:16:47.627 14 18
6 1 2016-12-20 17:27:58.930 14 19
7 1 2017-01-18 14:13:35.800 18 20
注意该列表如何显示authIds 14和15,即使它具有状态1但在较晚的日期具有不同的statusId。
我尝试过的一种方法如下:
select A1.id, A1.statusId, A1.updatedDate, A1.userId, A1.authId from AuthProgressTracker A1
left join AuthProgressTracker A2
on (A1.authId = A2.authId and A1.updatedDate > A2.updatedDate)
where A2.authId is not null
没有显示我正在寻找的结果。我尝试了另一个
SELECT *
FROM AuthProgressTracker T
INNER JOIN (
SELECT id, authId, statusId, MAX(updatedDate) as maxDate FROM AuthProgressTracker GROUP BY authId, statusId, id
) AP
ON AP.id = T.id AND T.updatedDate = AP.maxDate
order by T.id
这也没有产生预期的结果。
我错过了什么?
我如何分解SQL Server 2012中的问题,以便我能够在将来学会解决这样的问题?
答案 0 :(得分:2)
您的问题陈述可能会让您误入歧途,因为虽然您想要最新的记录,但时间戳可能不是您到达结果集的方式。在下面的查询中,我使用了一个子查询,该子查询标识了不除authId
以外的statusId
的所有1
。然后,它会过滤原始表格,为您提供所需的结果。
SELECT t1.*
FROM AuthProgressTracker t1
INNER JOIN
(
SELECT authId
FROM AuthProgressTracker
GROUP BY authId
HAVING SUM(CASE WHEN statusId <> 1 THEN 1 ELSE 0 END) = 0
) t2
ON t1.authId = t2.authId
答案 1 :(得分:0)
(您尚未说明您正在使用的RDBMS,因此您需要相应地调整查询。例如,如果使用mysql,请使用LIMIT
语法而不是TOP
。)
declare @AuthProgressTracker table (
id int,
statusId int,
updatedDate datetime,
userId int,
authId int
)
insert into @AuthProgressTracker
values
(1, 1, '2016-12-20 15:43:17.703', 14, 14),
(2, 1, '2016-12-20 15:54:01.523', 14, 15),
(3, 2, '2016-12-21 16:05:48.157', 14, 14),
(4, 3, '2016-12-21 16:27:58.610', 14, 15),
(5, 1, '2016-12-20 17:16:47.627', 14, 18),
(6, 1, '2016-12-20 17:27:58.930', 14, 19),
(7, 1, '2017-01-18 14:13:35.800', 18, 20)
/* Determine id's of latest status updates per authId */
SELECT MAX(id) as LatestSatus
FROM @AuthProgressTracker
GROUP BY authId
/* Note the above includes row id's you've chosen to exclude, so... */
/* Determine most recent statusId */
SELECT TOP 1 statusId
FROM @AuthProgressTracker
ORDER BY updatedDate DESC
/* Putting it all together */
SELECT i.*
FROM @AuthProgressTrackeri
INNER JOIN (
SELECT MAX(id) as LatestSatus
FROM @AuthProgressTracker
GROUP BY authId
) ls ON
ls.LatestSatus = i.id
WHERE i.statusId = (
SELECT TOP 1 statusId
FROM @AuthProgressTracker
ORDER BY updatedDate DESC
)