2011-01-08 7 views
11

To content tabela:Aktualizacja kolumny tak, że zawiera ona pozycję wiersza

ContentID | CategoryID | Position | Other1 | Other2 
=================================================== 
1   | 1   | NULL  | abcd | efgh 
2   | 1   | NULL  | abcd | efgh 
3   | 1   | NULL  | abcd | efgh 
4   | 2   | NULL  | abcd | efgh 
5   | 2   | NULL  | abcd | efgh 
6   | 2   | NULL  | abcd | efgh 

Są to pytania będę uruchomione:

SELECT ContentID FROM content WHERE CategoryID = 1 ORDER BY Position 
SELECT ContentID FROM content WHERE CategoryID = 2 ORDER BY Position 

Teraz chcę wdrożyć w górę, przesuń w dół, przejdź na górę i przejdź do dolnej funkcji zawartości. Wszystko, co muszę zrobić, to wypełnić kolumnę Pozycja numerami:

ContentID | CategoryID | Position 
================================= 
1   | 1   | 1 
2   | 1   | 2 
3   | 1   | 3 
4   | 2   | 1 
5   | 2   | 2 
6   | 2   | 3 

Czy można to osiągnąć za pomocą pojedynczego zapytania w MySQL? Coś jak:

UPDATE content 
SET Position = <ROW_NUMBER> 
WHERE CategoryID = 1 
ORDER BY Position 

UPDATE content 
SET Position = <ROW_NUMBER> 
WHERE CategoryID = 2 
ORDER BY Position 
+0

prawdopodobnie można użyć instrukcji CASE jakoś, ale dwie kwerendy może być lepiej. – dqhendricks

+0

@ Eveve: Właśnie udało mi się to zrobić. –

+0

'update content set position = id' –

Odpowiedz

11

To powinno działać

update 
content, 
(
    select 
    @row_number:=ifnull(@row_number, 0)+1 as new_position, 
    ContentID 
    from content 
    where CategoryID=1 
    order by position 
) as table_position 
set position=table_position.new_position 
where table_position.ContentID=content.ContentID; 

Ale wolałbym, aby zastosować ten pierwszy, na wyłączony użytkownik zdefiniowanej zmiennej

set @row_number:=0; 

Dodane przez Mchl:

można to zrobić w jedno oświadczenie takie jak to

update 
content, 
(
    select 
    @row_number:=ifnull(@row_number, 0)+1 as new_position, 
    ContentID 
    from content 
    where CategoryID=1 
    order by position 
) as table_position, 
(
    select @row_number:=0 
) as rowNumberInit 
set position=table_position.new_position 
where table_position.ContentID=content.ContentID; 
+0

Przetestuję to jutro. Czy możesz użyć tej samej tabeli w aktualizacji i wybrać? –

+0

Zależy. Jeśli korzystasz z powyższego przykładu, jest w porządku – ajreal

+0

Działa !!!!!!!!!!! –

0

początkowa:

UPDATE content as uc 
SET Position = (
    SELECT count(*) 
    FROM content as sc 
    WHERE sc.CategoryId = uc.CategoryId AND sc.Position is not null) 
WHERE uc.Position is null 
ORDER BY uc.ContentId 

przed włożeniem:

UPDATE content 
SET Position = Position+1 
WHERE Position >= newPos AND CategoryId = newCat 
+0

Daje mi ten błąd "Błąd SQL (1093): Nie można określić tabeli docelowej" uc "dla aktualizacji w klauzuli FROM". –

+0

Rozumiem. tylko sekundę. –

0

myślę, że byłoby bardzo żmudne, aby uruchomić dodatkowe pytania przez cały czas, kiedy wykonujesz pewne czynności na stole. Byłoby create a trigger, który uruchamia się za każdym razem, gdy chcesz wstawić/zaktualizować coś w tabeli.

W twoim przypadku zaleca się wywołanie BEFORE UPDATE i BEFORE INSERT. Jeśli chcesz również zachować czystość po usunięciu etntry, dodaj spust AFTER DELETE.

2

Oto rozwiązanie, które pracował dla mnie (mam nadzieję, że ktoś pomoże):

-- The following query re-populates the "Position" column with sequential numbers so that: 
-- a) sequence is reset to 1 for each "group" 
-- b) sequence is based on row number relative to each group depending on how ORDER BY is specified 
-- c) sequence does not disturb the original order but 
-- c.a) fixes NULLs so that they are moved to top 
-- c.b) fixes duplicate position values depending on how ORDER BY is specified 

-- ContentID is the primary key 
-- CategoryID is a foreign key 
-- Position column contains relative position of a record 

SET @current_group = NULL; 
SET @current_count = NULL; 

UPDATE 
content 
SET Position = CASE 
    WHEN @current_group = CategoryID THEN @current_count := @current_count + 1 
    WHEN @current_group := CategoryID THEN @current_count := 1 
END 
ORDER BY CategoryID, Position -- <Column 3>, <Column 4>, ... 
Powiązane problemy