Как увеличить значение столбца на основе предыдущего значения Row в SQL

Я использую SQL Server 2008.

У меня есть две таблицы: User_master и Item_master .

Существует Пользователь с user_id = 10.

|---------|
| user_id |
|---------|
|   10    |
|---------|

Есть 5 элементов с item_id = от 20 до 24.

|---------|---------|------------|
| item_id | user_id | item_order |
|---------|---------|------------|
|   20    |    10   |     0      |
|---------|---------|------------|
|   21    |    10   |     0      |
|---------|---------|------------|
|   22    |    10   |     0      |
|---------|---------|------------|
|   23    |    10   |     0      |
|---------|---------|------------|
|   24    |    10   |     0      |
|---------|---------|------------|

В Item_master есть еще один столбец item_order (int) . Я хочу разместить item_order = от 0 до 4 во всех этих строках только с одним запросом.

Является ли это возможным?

РЕДАКТИРОВАТЬ:

item_id не должен быть в порядке.

Например, вместо 20,21,22,23,24; это может быть 20,25,31,47,58.

4
nl ja de
Очень простым решением было бы вычесть 20 из item_id и использовать это: update item_master set item_order = item_id - 20 .
добавлено автор Daniel Hilgarth, источник
@RAS: Да, подумал. Вот почему я опубликовал комментарий, а не ответ. Однако он показывает, насколько важно определять ваши ограничения при задании вопроса.
добавлено автор Daniel Hilgarth, источник
@Ic, да, это основные ключи соответствующих таблиц.
добавлено автор RAS, источник
@DanielHilgarth, Спасибо за ответ, но, пожалуйста, см. Редактирование.
добавлено автор RAS, источник
является { item_id user_id } гарантировано уникальным?
добавлено автор lc., источник

3 ответы

Вы можете использовать функцию окна row_number() , чтобы назначать увеличивающееся число каждой строке с тем же user_id . Подзапрос требуется, потому что вы не можете использовать функции окна непосредственно в предложении set .

update  im
set     im.item_order = im.rn
from    (
        select  row_number() over (partition by user_id
                                   order by item_id) - 1 as rn
        ,       *
        from    item_master
        ) as im;

Живой пример в SQL Fiddle.

7
добавлено

Экстраполируя немного, и поскольку { item_id , user_id } уникален в таблице, вот общее решение:

UPDATE m
SET item_order = x.new_item_order
FROM item_master m
INNER JOIN (
  SELECT [item_id], [user_id], 
      (ROW_NUMBER() OVER (PARTITION BY [user_id] 
                          ORDER BY [item_id]))-1 AS [new_item_order] 
  FROM item_master
) x ON m.item_id = x.item_id AND m.user_id = x.user_id

Пример скрипта SQL

Это установит столбец item_order в порядке item_id для каждого пользователя, начиная с 0.

3
добавлено
@IC. Спасибо за ответ, но ответ Андомара намного проще.
добавлено автор RAS, источник
@RAS Да, ответ Андомара будет на один шаг проще, чем этот, потому что соединение, по-видимому, не является необходимым
добавлено автор lc., источник

Я предположил, что вы хотите группировать по пользователю, чтобы сгенерировать номер, и этот столбец item_order уже существует, просто требуется обновление?

update IM
    set item_order = t.RowNumber
FROM Item_master IM
INNER JOIN
    (select item_id , user_id , ROW_NUMBER() over(PARTITION BY user_id order by item_id ) -1 as 'RowNumber' from Item_master) T
    ON T.item_id = IM.item_id
1
добавлено
SqlCom.ru - Стиль жизни SQL
SqlCom.ru - Стиль жизни SQL
908 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только MS SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz). Предложения в @sql_ninja

SQL_Ninja
SQL_Ninja
340 участник(ов)

Правила чата - https://t.me/sqlcom/88269 @sqlcom - основной канал (только SQL) @sql_ninja - второй канал (SQL вопросы начального уровня и свободное общение) @Gopnegbot - Викторина по SQL Server (наберите в привате /quiz)