如何使用秩列维护有序列表?(sql)

如何使用秩列维护有序列表?(sql),sql,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并更新新旧排名之间的每一行更聪明的方法

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

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并更新新旧排名之间的每一行更聪明的方法

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


如果不是,另一种方法(一种欺骗)是对你的排名使用小数,并给Ben分配一个值1.5:)这是假设你没有直接从数据库中显示排名。

你的排名能够根据你可以排序的其他列动态计算吗?如果是这样,那么您可以在一些RDBMS中使用ROW_NUMBER函数来相应地计算和更新您的排名


如果不是,另一种方法(有点欺骗)是对你的排名使用小数,并给Ben赋值1.5:)这是假设你没有直接从数据库显示排名。

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

从TableName中选择@CurrentRank=Rank,其中Id=@SelectedId
更新表名
设置秩=
案例
当Id=@SelectedId时,则为@newselectedBank
当@NewSelectedRank<@CurrentRank
和Rank>=@NewSelectedRank和Rank<@CurrentRank
然后秩=秩+1
当@NewSelectedRank>@CurrentRank
和Rank@CurrentRank
然后秩=秩-1
结束

由于有一些反复,我将这样做(使用SQL Server表示法):

从TableName中选择@CurrentRank=Rank,其中Id=@SelectedId
更新表名
设置秩=
案例
当Id=@SelectedId时,则为@newselectedBank
当@NewSelectedRank<@CurrentRank
和Rank>=@NewSelectedRank和Rank<@CurrentRank
然后秩=秩+1
当@NewSelectedRank>@CurrentRank
和Rank@CurrentRank
然后秩=秩-1
结束

这里是另一种方法。这将避免重复密钥问题(假设您对秩有唯一的约束)。如果等级低于当前等级,则更新为工作

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
声明@ID int、@NewRank int、@CurrentRank int、@LowRank int、@HighRank int
设置@ID=400
设置@NEWRANK=2
从MyTable中选择@CurrentRank=Rank,其中Id=@Id
当@NewRank<@CurrentRank然后@NewRank ELSE@CurrentRank END时设置@LowRank=CASE
当@NewRank<@CurrentRank然后@CurrentRank ELSE@NewRank END时,设置@HighRank=CASE
更新MyTable SET Rank=-Rank,其中排名介于@LowRank和@HighRank之间
更新MyTable SET Rank=@NewRank,其中ID=@ID
更新MyTable集合排名=
案例
当@NewRank<@CurrentRank时,则为-Rank+1
ELSE-排名-1
结束
其中秩<0

这里是另一种方法。这将避免重复密钥问题(假设您对秩有唯一的约束)。如果等级低于当前等级,则更新为工作

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
声明@ID int、@NewRank int、@CurrentRank int、@LowRank int、@HighRank int
设置@ID=400
设置@NEWRANK=2
从MyTable中选择@CurrentRank=Rank,其中Id=@Id
当@NewRank<@CurrentRank然后@NewRank ELSE@CurrentRank END时设置@LowRank=CASE
当@NewRank<@CurrentRank然后@CurrentRank ELSE@NewRank END时,设置@HighRank=CASE
更新MyTable SET Rank=-Rank,其中排名介于@LowRank和@HighRank之间
更新MyTable SET Rank=@NewRank,其中ID=@ID
更新MyTable集合排名=
案例
当@NewRank<@CurrentRank时,则为-Rank+1
ELSE-排名-1
结束
其中秩<0

如果您想对它产生不必要的幻想(或者有其他理由这样做),并且您可以计划只使用单个更新查询更新正在移动的单行的列组,您可以使用触发器强制其他行更新。这将按以下方式进行:

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

我基本上是想指出,这是可以做的事情的方式,不建议这样做。如果您不熟悉将应用于该表的所有其他逻辑,则不建议使用该选项;如果这是一个有其他事情在进行的大型项目,您可能需要非常小心,因为触发器可能很复杂

如果您想对它产生不必要的幻想(或者有其他理由这样做),并且您可以计划只使用单个更新查询更新正在移动的单行的列组,您可以使用触发器强制其他行更新。这将按以下方式进行:

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

我基本上是想指出,这是可以做的事情的方式,不建议这样做。如果您不熟悉将应用于该表的所有其他逻辑,则不建议使用该选项;如果这是一个有其他事情在进行的大型项目,您可能需要非常小心,因为触发器可能很复杂

在哪个基础上,您决定rankIt看起来只是另一个字段。排名上是否有“唯一”索引约束?是的,至少我认为它应该是唯一的,因为不应该有两行具有相同排名。是的,它只是另一列。在此基础上,您决定rankIt看起来只是另一个字段。排名上是否有“唯一”索引约束?是的,至少我认为它应该是唯一的,因为不应该有两行具有相同排名。是的,它只是另一列。不,它们只是用户可以分配给行的“等级”(想想一个用户界面,您可以在其中拖放列表项来“排列”它们)-我不确定我是否理解有小数等级的意义。小数等级允许您在两行之间更新一行,而不接触任何其他行。例如,如果您知道Ben介于John和Steve之间,并且您知道Steve的值为2,那么