2013-06-11 3 views
3

У меня есть таблица «MyData» с некоторыми данными данных:как нормализовать/обновлять столбец «заказ»

id name  position 
=========================== 
4  foo  -3 
6  bar  -2 
1  baz  -1 
3  knork  -1 
5  lift  0 
2  pitcher 0 

я принести стол упорядоченного используя order by position ASC;

значение столбца позиции может быть не уникальный (по какой-то причине не описанный здесь :-) и используется для предоставления пользовательского заказа во время SELECT.

то, что я хочу сделать:

я хочу, чтобы нормализовать столбца таблицы «позицию», связывая уникальную позицию каждой строки, которая не суммируется и не уничтожить заказ. кроме того, самое высокое положение после нормализации должно быть -1.

хотел результирующее содержимое таблицы:

id name  position 
=========================== 
4  foo  -6 
6  bar  -5 
1  baz  -4 
3  knork  -3 
5  lift  -2 
2  pitcher -1 

я пытался несколько способами, но не сумел реализовать оператор правильноupdate.

я предполагаю, что использование

generate_series(-(select count(*) from mydata), -1) 

является хорошей отправной точкой, чтобы получить новые значения для столбца позиции, но я понятия не имею, как объединить, что сгенерированные данные столбцов в отчете обновления.

надежда кто-то может помочь мне :-)

ответ

6

Что-то вроде:

with renumber as (
    select id, 
     -1 * row_number() over (order by position desc, id) as rn 
    from foo 
) 
update foo 
    set position = r.rn 
from renumber r 
where foo.id = r.id 
    and position <> r.rn; 

SQLFiddle Demo

+2

Для исполнения добавьте 'и position <> r.rn' в предложение where. Иначе вы закончите переписывание многих строк, которые не должны. –

+0

@Denis: хорошая точка.Хотя я думаю, что это, вероятно, не изменится очень сильно. –

+0

Это может быть огромным, когда в большинстве строк содержится правильное значение (это часто бывает для упорядочения индексов). :-) Если вся таблица была переписана запросом, рекомендуется сразу (и вручную) вакуумировать. –

0
update mydata temp1, (select a.*,@var:[email protected] sno from mydata a, (select @var:=0) b 
order by position desc, id asc) temp2 
set temp1.position = temp2.sno 
where temp1.id = temp2.id; 
+2

Это не действует SQL для Postgres –

+0

ой жаль, что я только что видел SQL теги и написал для MySQL – chetan

+0

SQL является * только * язык запросов. Основываясь на теге, вы никогда не сможете принять конкретную СУБД. –

2

Попробуйте один -

запрос:

CREATE TABLE temp 
(
     id INT 
    , name VARCHAR(10) 
    , position INT 
) 

INSERT INTO temp (id, name, position) 
VALUES 
    (4, 'foo', -3), 
    (6, 'bar', -2), 
    (1, 'baz', -1), 
    (3, 'knork', -1), 
    (5, 'lift', 0), 
    (2, 'pitcher', 0) 

SELECT 
     id 
    , name 
    , position = -ROW_NUMBER() OVER (ORDER BY position DESC, id) 
FROM temp 
ORDER BY position 

Update:

UPDATE temp 
SET position = t.rn 
FROM (
    SELECT id, rn = - ROW_NUMBER() OVER (ORDER BY position DESC, id) 
    FROM temp 
) t 
WHERE temp.id = t.id 

Выход:

id   name  position 
----------- ---------- -------------------- 
4   foo  -6 
6   bar  -5 
3   knork  -4 
1   baz  -3 
5   lift  -2 
2   pitcher -1 
+2

Построение таблицы «temp» не будет работать с Postgres. Хорошая точка в добавлении столбца 'id' к порядку функции окна. –

+0

@a_horse_with_no_name, спасибо за комментарий. См. Обновленный ответ. – Devart

+0

кажется не на 100% правильным, но рядом с правдой. см. http://sqlfiddle.com/#!1/d1770/6 – lgersman

1

@a_horse_with_no_name действительно близок к истине - спасибо!

UPDATE temp 
    SET position=t.rn 
    FROM (SELECT 
      id, name, 
      -((select count(*) 
      FROM temp) 
      +1-row_number() OVER (ORDER BY position ASC)) as rn 
     FROM temp) t 
    WHERE temp.id=t.id; 

SELECT * FROM temp ORDER BY position ASC; 

см http://sqlfiddle.com/#!1/d1770/6

+0

Хмм, я не вижу другого результата, чем с моим решением. Я не думаю, что 'count (*)' необходимо в подвыборке, потому что наивысший 'row_number()' автоматически будет таким же, как 'count (*)'. Вот почему я использовал порядок DESC. –

+0

Я принял инструкцию по обновлению и применил ее к различным тестовым данным, и порядок после публикации обновлен (см. Http://sqlfiddle.com/#!1/84f5f/6). мое решение (полученное из ваших :-) хорошо работает с обоими тестовыми данными (см. http://sqlfiddle.com/#!1/d1770/6). – lgersman

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