我在SQL Server中有一张表,上面有Id, Plan_Id, sequence_no
和以下数据。
Id Plan_Id sequence_no
----------- ------------ -----------
1132507748 1167096719 0
1102670655 1167096719 1
1166210290 1167096719 2
因此,我在网站上根据 sequence_no 列出了这些记录。用户可以使用拖放对这些记录进行排序。
我这里想要的是,当用户将第1条记录拖到第0位时,我想对表中的所有记录重新排序。我有Id,Plan_id和新的sequence_no作为过程的参数。我尝试使用下面的代码,但无法正常工作。
update dbo.planRecords
set sequence_no = sequence_no+1
where plan_id = @plan_id and sequence_no >= @newPosition
如何重新排序这些记录?
答案 0 :(得分:2)
最简单的解决方案是不使用int,而使用十进制。这样,您只需要知道记录的两个最接近的同级,并且只需将sequence_no的值更改为它们之间的数字即可。
例如,如果您的数据库中有以下记录:
Id Plan_Id sequance_no
----------- ------------ -----------
1132507748 1167096719 1.0
1102670655 1167096719 2.0
1166210290 1167096719 3.0
1132507763 1167096719 4.0
1102670623 1167096719 5.0
1166210299 1167096719 6.0
并且您想将记录5.0移至1.0到2.0之间,您所要做的就是将其sequence_no更新为1.5:
Id Plan_Id sequance_no
----------- ------------ -----------
1132507748 1167096719 1.0
1102670623 1167096719 1.5
1102670655 1167096719 2.0
1166210290 1167096719 3.0
1132507763 1167096719 4.0
1166210299 1167096719 6.0
Decimal最多支持38位数字,因此您最多可以使用小数点右边的37位数字,因此即使您在记录顺序上有很多更改,我也很确定您不必担心插槽用完了。
如果要按整数显示记录的顺序,则始终可以使用row_number() over(order by sequence_no)
获得很好的int值显示。
答案 1 :(得分:1)
在移动项目之前,您需要先了解旧位置。根据项目是向上移动还是向下移动,您的逻辑需要不同。该过程的粗略概述(未经测试)如下:
DECLARE @Id INT = 1100000004; -- this id
DECLARE @NewPosition INT = 1; -- needs to have this position
WITH RowToMove AS (
-- using cte instead of variables
SELECT Plan_Id, sequence_no AS OldPosition
FROM planRecords
WHERE Id = @Id
), RowsToUpdate AS (
-- columns used inside set and where clause of the update statement
SELECT Id, sequence_no, OldPosition
FROM planRecords
CROSS JOIN RowToMove
-- select rows that belong to same category and position between old and new
WHERE planRecords.Plan_Id = RowToMove.Plan_Id AND sequence_no BETWEEN
CASE WHEN OldPosition < @NewPosition THEN OldPosition ELSE @NewPosition END AND
CASE WHEN OldPosition > @NewPosition THEN OldPosition ELSE @NewPosition END
)
UPDATE RowsToUpdate SET sequence_no = CASE
WHEN Id = @Id THEN @NewPosition -- this is the row we are moving
WHEN OldPosition < @NewPosition THEN sequence_no - 1 -- row was moved down, move other rows up
WHEN OldPosition > @NewPosition THEN sequence_no + 1 -- row was moved up, move other rows down
END;
在DBFiddle using variables,using CTE上的演示