2013-11-19 2 views
3

мне нужно, чтобы изменить порядок элементов в таблице, как показано в следующем примере:Как изменить порядок строк с помощью SQL (не менять)

Original: 
Id Pos (int) 
--------- 
a  1 
b  2 
c  3 
d  4 
e  5 

I need this result after moving d to the second row: 
Id Pos (int) 
--------- 
a  1 
b  3 
c  4 
d  2 
e  5 

Как вы можете видеть, это не простая замена, и мне нужно увеличьте положение на 1 после позиции вставки и оставьте строки перед тем, как вставить их. Я попытался разрешить это следующим образом:

UPDATE [Table] SET Pos = 2 WHERE Id = 'd' 

MERGE INTO [Table] T USING 
(
    SELECT ROW_NUMBER() OVER(ORDER BY Pos) AS Position, Id FROM [Table] 
) S 
ON T.Id = S.Id 
WHEN MATCHED THEN UPDATE SET Pos = S.Position; 

Однако после обновления две строки имеют одинаковое положение. Вероятно, он не будет правильно отсортирован.

Вы можете генерировать данные примера, используя скрипт ниже:

CREATE TABLE [Table] (
    Id char NOT NULL, 
    Pos int NOT NULL, 
    CONSTRAINT [PK_Table_Id] PRIMARY KEY CLUSTERED ([Id]) 
) 
GO 
INSERT INTO [Table] (Id, Pos) VALUES ('a', 1),('b', 2),('c', 3),('d', 4),('e', 5) 
+0

Там не совсем достаточно информации здесь, чтобы понять, в чем проблема. Читая только SQL, я ожидал бы, что оператор слияния не будет иметь никакого влияния, поскольку он будет постоянно записывать существующее положение. Можете ли вы включить полный образец, включая инструкцию create table, вставить некоторые примеры данных и включить существующий сценарий, чтобы мы могли протестировать локально? – David

+0

Вы должны лучше описать, что правила связаны с «переупорядочением». Скорее всего, самое лучшее, что вы можете сделать, это найти способ упорядочить ключевой столбец так, как вы хотите его увидеть (даже уродливое решение), а затем перечислить все. –

ответ

7
DECLARE @id CHAR(1) = 'd'; 
DECLARE @newpos INT = 2; 
DECLARE @oldpos INT; 

BEGIN TRANSACTION 
    SELECT @oldpos = Pos FROM Table WHERE id = @id; 
    IF @newpos < @oldpos 
    UPDATE #Table SET Pos = Pos + 1 
    WHERE Pos >= @newpos AND Pos < @oldpos; 
    ELSE 
    UPDATE #Table SET Pos = Pos - 1 
    WHERE Pos >= @newpos AND Pos > @oldpos; 

    UPDATE #Table SET Pos = @newpos 
    WHERE Id = @id; 
COMMIT TRANSACTION 
+0

Ну, этот скрипт не идеален, мне нужно запустить его дважды, чтобы сделать убедитесь, что окончательный заказ достигнут. – KMX

Смежные вопросы