Tsql 动态重新排序SQL Server表中的列值

Tsql 动态重新排序SQL Server表中的列值,tsql,sql-server-2017,Tsql,Sql Server 2017,我有一个SQL Server用户技能表,每个用户的优先级顺序如下: +----+------+----------+----------+ | ID | user | skill | priority | +----+------+----------+----------+ | 1 | foo | swimming | 1 | +----+------+----------+----------+ | 2 | foo | running | 2 |

我有一个SQL Server用户技能表,每个用户的优先级顺序如下:

+----+------+----------+----------+
| ID | user | skill    | priority |
+----+------+----------+----------+
| 1  | foo  | swimming | 1        |
+----+------+----------+----------+
| 2  | foo  | running  | 2        |
+----+------+----------+----------+
| 3  | foo  | hunting  | 3        |
+----+------+----------+----------+
| 4  | boo  | swimming | 1        |
+----+------+----------+----------+
| 5  | moo  | swimming | 1        |
+----+------+----------+----------+
| 6  | moo  | running  | 2        |
+----+------+----------+----------+
当其中一项技能的优先级值更改时,如何编写SQL代码以将优先级列值重新排序为用户所有技能的整数

例如:对于用户foo,我会将技能游泳的优先级从1更改为2;update语句还必须以动态方式更改该用户所有其他技能的优先级


因此,在该示例中,游泳的优先级将是2而不是1,运行的优先级将是1而不是2,其他优先级将保持不变。

在这个答案中,我假设您希望使用SQL而不是C来执行此操作。基于该假设,单个事务中的这两个SQL语句将指定技能的优先级提高1

'Set @User to the required user and @Skill to the required skill.

'Decrease the priority of the user's skill above the specified skill.
UPDATE MyTable
SET    priority = priority + 1
WHERE  user = @User 
AND    priority = (SELECT priority - 1 
                   FROM MyTable 
                   WHERE user = @User
                   AND skill = @Skill)

'Increase the specified skill's priority.
UPDATE MyTable
SET    priority = priority - 1
WHERE  user = @User
AND    skill = @Skill
AND    priority > 1
以类似的方式,这两条SQL语句将指定的技能提高到指定的优先级

'Set @User to the required user and @Skill to the required skill.
'Set @NewPriority to the new priority.

'Decrease the higher-prioritised skills.
UPDATE MyTable
SET    priority = priority + 1
WHERE  user = @User 
AND    priority >= @NewPriority 
AND    priority < (SELECT priority
                   FROM MyTable 
                   WHERE user = @User
                   AND skill = @Skill)

'Set the specified skill's priority as requested.
UPDATE MyTable
SET    priority = @NewPriority 
WHERE  user = @User
AND    skill = @Skill
AND    priority > 1
'Set @User to the required user and @Skill to the required skill.
'Set @NewPriority to the new priority.

'Decrease the higher-prioritised skills to
'handle case where new priority is higher.
UPDATE MyTable
SET    priority = priority + 1
WHERE  user = @User 
AND    priority >= @NewPriority 
AND    priority < (SELECT priority
                   FROM MyTable 
                   WHERE user = @User
                   AND skill = @Skill)

'Increase the lower-prioritised skills to
'handle case where new priority is lower.
UPDATE MyTable
SET    priority = priority - 1
WHERE  user = @User 
AND    priority <= @NewPriority 
AND    priority > (SELECT priority
                   FROM MyTable 
                   WHERE user = @User
                   AND skill = @Skill)    

'Set the specified skill's priority as requested.
UPDATE MyTable
SET    priority = @NewPriority 
WHERE  user = @User
AND    skill = @Skill
这三条SQL语句将指定的技能移动到指定的优先级

'Set @User to the required user and @Skill to the required skill.
'Set @NewPriority to the new priority.

'Decrease the higher-prioritised skills.
UPDATE MyTable
SET    priority = priority + 1
WHERE  user = @User 
AND    priority >= @NewPriority 
AND    priority < (SELECT priority
                   FROM MyTable 
                   WHERE user = @User
                   AND skill = @Skill)

'Set the specified skill's priority as requested.
UPDATE MyTable
SET    priority = @NewPriority 
WHERE  user = @User
AND    skill = @Skill
AND    priority > 1
'Set @User to the required user and @Skill to the required skill.
'Set @NewPriority to the new priority.

'Decrease the higher-prioritised skills to
'handle case where new priority is higher.
UPDATE MyTable
SET    priority = priority + 1
WHERE  user = @User 
AND    priority >= @NewPriority 
AND    priority < (SELECT priority
                   FROM MyTable 
                   WHERE user = @User
                   AND skill = @Skill)

'Increase the lower-prioritised skills to
'handle case where new priority is lower.
UPDATE MyTable
SET    priority = priority - 1
WHERE  user = @User 
AND    priority <= @NewPriority 
AND    priority > (SELECT priority
                   FROM MyTable 
                   WHERE user = @User
                   AND skill = @Skill)    

'Set the specified skill's priority as requested.
UPDATE MyTable
SET    priority = @NewPriority 
WHERE  user = @User
AND    skill = @Skill

其他一些示例将很有帮助,特别是对于边缘情况。例如:如果foo/swiming的优先级更改为0,那么foo/running是否应该为1?如果foo/swiming更改为5,该怎么办?SQL Server不会以任何特定顺序存储或检索项。查询是使用微处理器中的不同内核并行完成的,因此必须始终使用OrderBy对结果进行排序。@jdweng,这个问题与行的存储或检索顺序无关。它是关于为一个用户的每一行分配新的优先级值,每当该用户的一个优先级值被更改时。@HABO,第一个答案是处理行删除后的重新排序。这个问题是关于普通的重新排序,不删除行。@HABO,至于您链接的第二个答案,SQL代码确实很长,很复杂,而且通常很糟糕。我甚至不确定它是否正确。在问题评论中进一步澄清后,OP似乎希望能够对一项技能的优先级进行更新,使其位于用户拥有n项技能的1-n范围内的任何位置。然后,所有其他技能的优先级应根据需要向上或向下调整,以填充该范围1-n中的其余值。@Richard,我已添加代码以满足此要求。@RoadWarrior根据我从您的代码中了解,我应该使用存储过程中的最后一部分——三条语句,因为它替换了前两部分中的旧答案?@Sherif,与我在前两个代码部分中提到的其他更简单的用例不同,如果您想将某项技能的优先级重新分配到任何位置,这是正确的。@如果您想使操作原子化,请注意单个事务中的SQL语句。