如何使用排名列维护有序列表? (SQL)

时间:2012-06-18 12:44:09

标签: sql

考虑一个包含以下列的表:

ID, Name, Rank

数据如:

100, John, 1
200, Steve, 2
300, Mike, 3
400, Ben, 4
500, Jake, 5

排名是独一无二的。

如果我想给Ben排名2并更新其余部分以便我最终得到

,那么更新表格的最佳方式是什么?
100, John, 1
400, Ben, 2
200, Steve, 3
300, Mike, 4
500, Jake, 5

有没有更聪明的方法来做到这一点,而不是将Ben的排名改为2并更新他的新老排名之间的每一行?

4 个答案:

答案 0 :(得分:2)

这是另一种方法。这将避免重复键问题(假设您对Rank有唯一约束)。如果排名低于当前排名,则更新为工作。

DECLARE @ID int, @NewRank int, @CurrentRank int, @LowRank int, @HighRank int
SET @ID=400
SET @NEWRANK=2

SELECT @CurrentRank = Rank FROM MyTable WHERE Id = @ID
SET @LowRank = CASE WHEN @NewRank < @CurrentRank THEN @NewRank ELSE @CurrentRank END
SET @HighRank = CASE WHEN @NewRank < @CurrentRank THEN @CurrentRank ELSE @NewRank END

UPDATE MyTable SET Rank = -Rank WHERE Rank BETWEEN @LowRank AND @HighRank

UPDATE MyTable SET Rank = @NewRank WHERE ID = @ID

UPDATE MyTable SET Rank = 
    CASE 
    WHEN @NewRank < @CurrentRank THEN  -Rank + 1
    ELSE -Rank - 1
    END
WHERE Rank < 0

答案 1 :(得分:1)

是否可以根据您可以订购的其他列动态计算yoru排名?如果是这样,那么您可以在某些RDBMS中使用ROW_NUMBER函数来相应地计算和更新您的排名。

如果没有,另一种方法(作弊的类型)将使用小数作为你的等级,并指定Ben的值为1.5 :)这假设你没有直接从你的数据库显示等级。

答案 2 :(得分:1)

由于有一些来回,我就是这样做的(使用SQL Server表示法):

SELECT @CurrentRank = Rank FROM TableName WHERE Id = @SelectedId

UPDATE TableName
SET Rank= 
CASE
    WHEN Id = @SelectedId THEN @NewSelectedRank
    WHEN @NewSelectedRank < @CurrentRank 
        AND Rank >= @NewSelectedRank AND Rank < @CurrentRank
    THEN Rank = Rank + 1
    WHEN @NewSelectedRank > @CurrentRank 
        AND Rank <= @NewSelectedRank AND Rank > @CurrentRank
    THEN Rank = Rank - 1
END

答案 3 :(得分:1)

如果你想对它有所不必要(或者有其他理由这样做),你可以计划只用一个更新查询来更新被移动的单行的等级,你可以使用一个触发器强制其他行更新。这将按如下方式完成:

CREATE OR REPLACE TRIGGER [dbo].[tr_RankChange]
  ON [dbo].[table_name]  Before UPDATE AS 
  BEGIN 
    Update [dbo].[table_name] Set Rank = Rank + 1 Where rank >= New.Rank
    Update [dbo].[table_name] Set Rank = Rank - 1 Where rank >= Old.Rank
  END

我基本上想指出它可以通过某种方式完成,而不是建议这样做。如果您不熟悉将应用于表格的所有其他逻辑,则不建议这样做;如果这是一个包含其他事情的大型项目,您可能需要非常小心,因为触发器可能很复杂。