2016-02-18 9 views
6

Mam tabelę Items np.Przenoszenie i ponowne zamawianie rekordów na stałe

ID Name  ItemOrder 
---------------------- 
16 Albania 1 
13 Chile 2 
11 Barbados 3 
10 France 4 
... 

Które wyświetlać w mojej aplikacji klienckiej jako

SELECT * FROM Items ORDER BY ItemOrder 

Chcę być w stanie „przenieść” na przykład Albania i Barbados Po (lub przed w zależności od mojego parametru) France lub inny rekord . więc wynik jest (dla ruchu After rekordowym France):

13 Chile 1  
10 France 2 
16 Albania 3 
11 Barbados 4 

I wynik dla Before jest:

13 Chile 1   
16 Albania 2 
11 Barbados 3 
10 France 4 

muszę aktualizacji na stałe ItemOrder odzwierciedlać nowy porządek. Czy istnieje prosty i skuteczny sposób na zrobienie tego?

+1

Jak w e wiemy, który rekord "poruszać się" w miejscu, w którym (co naprawdę się nie porusza, jego kolejność)? – sagi

+0

@Sagi, Tak, muszę zaktualizować ItemOrder, aby odzwierciedlić nowe zamówienie – zig

+0

są tylko 4 rekordy w tabeli – TheGameiswar

Odpowiedz

5

Można użyć wyrażenia wspólnym stole (CTE), aby wykonać operację UPDATE. W ten sposób zapytanie może wyglądać na „po” wypadku:

;WITH ToUpdate AS (
    SELECT ID, Name, ItemOrder, 
     ROW_NUMBER() OVER (ORDER BY temp_order) AS NewOrder 
    FROM (
    SELECT ID, Name, ItemOrder, 
     CASE 
      WHEN Name IN ('Albania', 'Barbados') THEN x.o + ItemOrder * 0.1 
      ELSE ItemOrder 
     END AS temp_order 
    FROM mytable 
    CROSS JOIN (SELECT ItemOrder FROM mytable WHERE Name = 'France') AS x(o)) AS t 
) 
UPDATE ToUpdate 
SET ItemOrder = NewOrder 

Sztuką jest, aby France's numer zamówienia i dodać frakcji rzędu „Albania”, „Barbados”, tak że :

  • „Albania”, „Barbados” umieszczone są po „Francja”
  • „Albania” i „Barbados” utrzymać porządek między nimi
  • kolejność zapisów następujących „Francja” jest również utrzymana .

Demo here

Edit:

'przed' sprawa może zostać zrealizowany, jeśli podstawimy tę linię:

WHEN Name IN ('Albania', 'Barbados') THEN x.o + ItemOrder * 0.1 

z tej linii:

WHEN Name IN ('Albania', 'Barbados') THEN x.o - 1.0/ItemOrder * 0.1 
+0

Co oznaczają 'x.o' i' x (o) '? – zig

+0

@zig Jest to tylko alias używany do uzyskiwania dostępu do wyniku zwracanego przez operację 'CROSS JOIN'. –

+0

To wydaje się działać dobrze. Wciąż testowałem (nie udało mi się jeszcze w pełni zrozumieć tego kodu) Próbowałem zrobić 'Before' zmieniając' xo + ItemOrder * 0.1' na 'xo - ItemOrder * 0.1', ale wynik jest odwrócony, chociaż rekordy to Before France, ale zamówienie nie utrzymuje między nimi "Albania", "Barbados". Czy możesz pokazać mi, jak zrobić "Przed"? – zig

1

(Uwaga: Ta odpowiedź została napisana przed zaktualizowane pytanie wspomnieć, że trzeba aktualizacji ItemOrder.)

pierwsze, że niektóre miejsca między swoimi wpisami:

SELECT ID, name, ItemOrder * 10 AS newOrder FROM Items 

Teraz modyfikujemy ten SQL, aby wstawić "specjalne" pomiędzy:

SELECT ID, name, ItemOrder 
     CASE WHEN name = 'Albania' 
      THEN (SELECT ItemOrder FROM Items WHERE name = 'France') * 10 + 1 
      WHEN name = 'Barbados' 
      THEN (SELECT ItemOrder FROM Items WHERE name = 'France') * 10 + 2 
      ELSE ItemOrder * 10 
     END AS newOrder 
    FROM Items 

A teraz możemy sortować według niego:

SELECT ID, name, ItemOrder 
    FROM (... see previous SQL ...) AS t 
ORDER BY newOrder