我有一个表格,其中包含一个名为“得分”的列。我想编写一个循环遍历此表中所有行的过程,并确定所有行中的每个行,每个特定的行列,即最高分为1级,最小分= n。
到目前为止,这是我的不良尝试:
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @Rank INT = 0;
DECLARE @UserID UNIQUEIDENTIFIER;
DECLARE cur CURSOR FOR SELECT UserID FROM tblMember
OPEN cur
FETCH NEXT FROM cur INTO @UserID
--loop through all users
WHILE @@FETCH_STATUS = 0 BEGIN
SELECT @Rank = ROW_NUMBER() OVER(ORDER BY Score DESC) FROM tblDetails WHERE UserID = @UserID;
PRINT @Rank
Print ' For '
Print @UserID;
UPDATE tblDetails SET Rank = @Rank WHERE UserID = @UserID;
FETCH NEXT FROM cur INTO @UserID
END
END
不幸的是,这项工作将每个条目排名为1 - 可能是因为查询具有WHERE子句来细化结果集。但我无法确定正确的查询应该是什么!
答案 0 :(得分:6)
WITH q AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY userId ORDER BY score DESC) rn
FROM tblDetail
)
UPDATE q
SET rank = rn
答案 1 :(得分:0)
我相信您想要的正确查询是:
with toupdate as (
select d.*,
row_number() over (order by score desc) as seqnum
from tblDetails
)
update toupdate
set [rank] = seqnum;
我使用了row_number()
因为你的例子。如果您希望具有相同值的分数具有相同的排名,则可能需要rank()
或dense_rank()
:
with toupdate as (
select d.*,
rank() over (order by score desc) as seqnum
from tblDetails
)
update toupdate
set [rank] = seqnum;
重要的区别是查询中没有partition by
子句。
答案 2 :(得分:0)
可能基于您尝试更新的用户ID或增加排名列。因此,根据我的理解,您想要更新的用户ID = 1等级列
declare @t INT;
SELECT @t = MAX(Userid) From tblDetails
;
with cte(w) as
(select 1
UNION ALL
Select Userid + 1
From
tblDetails where Userid < @t)
UPdate tblDetails
set [Rank]=cte.w
FROM cte
INNER JOIN tblDetails S
ON S.Userid = cte.w