2012-06-18 35 views
1

考虑一个表有以下栏目:如何使用等级列维护有序列表? (SQL)

ID, Name, Rank 

和数据,如:

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

的排名是独一无二的。

有什么更新的表,如果我想给奔2的等级和相应的更新休息,这样我会

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

最终的最好的办法是有一个更聪明的办法做到这一点比将Ben的等级改为2并更新他的新旧等级之间的每一行?

+2

你在哪个基础上决定排名 – 2012-06-18 12:47:20

+0

看起来它只是另一个领域。 – beerbajay

+0

Rank是否存在“Unique”INDEX约束? –

回答

1

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

如果不是,另一种方法(一种作弊的)是使用小数为您的排名,并指定本值1.5 :)这是假设你是不是直接从数据库显示的排名。

+0

不用,它们是用户可以分配给行的“正好排名”(想想一个用户界面,在这里你可以拖放列表项来“排列”它们) - 我不确定是否理解有小数点秩。 – wannabeartist

+0

十进制等级将允许您更新两行之间的一行而不触及任何其他行。例如,如果您知道Ben在John和Steve之间,并且您知道Steve的值为2,并且John的值为1,那么为Ben分配值为1.5的值不会让您更新任何其他人。 –

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

如果你想成为不必要的花哨它(或有其他原因做这种方式),你可以计划刚刚更新单个行的排名就动了一个更新查询,您可以使用触发器强制更新其他行。这将做如下:

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 

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

+0

好的,谢谢,鉴于我的SQL技能太差,我想我会坚持更简单的解决方案 – wannabeartist

+0

好;我想确保提出这个想法,以便那些看到这个问题的人知道这是一个选择,但它有缺点。 –