首页 > 解决方案 > SQL查询,循环数据

问题描述

我有一个包含以下字段的数据库:UserID、DateRecorded 和 Score。

每次更新分数时都会向表中添加一个新条目。以下是用户记录的示例:

UserID | DateRecorded | Score
3 | 21-08-2019 | 10
3 | 23-08-2019 | 5
3 | 21-09-2019 | 10
3 | 21-08-2018 | 1

从查询中,我希望它只显示所有具有最早 DateRecorded 的用户的分数。

虽然对游标不太熟悉,但我尝试使用网上的一个示例并将其改编为我的,但这似乎并没有奏效。这是我对光标的尝试:

DECLARE @DateRecorded AS DATETIME;
DECLARE @scores AS FLOAT;
DECLARE @Cursor as CURSOR;

SET @Cursor = CURSOR FOR
select [user_id], [DateRecorded], scores
from myTable
where [user_id] = '55'

OPEN @Cursor
FETCH NEXT FROM @Cursor INTO @UserID, @DateRecorded, @scores;

WHILE @@FETCH_STATUS = 0
BEGIN
 SELECT @UserID AS 'User ID', MIN(@DateRecorded) AS 'Date', @scores AS 'Score';
 FETCH NEXT FROM @Cursor INTO @UserID, @DateRecorded, @scores;
END

CLOSE @Cursor;
DEALLOCATE @Cursor;

这是我期待的结果:

3 | 21-08-2018 | 1

有没有比使用游标更简单的方法?

我完全误解了游标吗?

谢谢你的帮助

标签: sqlsql-serverloopscursorgreatest-n-per-group

解决方案


不要使用游标和循环(除非你别无选择):它们很复杂,而且非常慢。您在这里要求的内容可以通过直接的 SQL 查询来完成。

如果您只想要每个用户的最早记录日期而不需要其他信息,那么简单的聚合就足够了:

select UserIdD, min(DateRecorded) from mytable group by UserID

如果您想要每个用户的整个“第一条”记录,那么这是一个典型的每组最大 n 问题。一种方法是使用相关子查询进行过滤:

select t.*
from mytable t
where t.DateRecorded = (
    select min(t1.DateRecorded) from mytable t1 where t1.UserID = t.UserID
)

您可能还喜欢反left join解决方案:

select t.*
from mytable t
left join mytable t1 on t1.UserID = t.UserID and t1.DateRecorded < t.DateRecorded
where t1.UserID is null

推荐阅读