SQL过程获取行号以确定“排名”

时间:2014-06-20 21:48:35

标签: sql sql-server stored-procedures

我有一个表格,其中包含一个名为“得分”的列。我想编写一个循环遍历此表中所有行的过程,并确定所有行中的每个行,每个特定的行列,即最高分为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子句来细化结果集。但我无法确定正确的查询应该是什么!

3 个答案:

答案 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