Обновить значение в том же первичном ключе

#sql #sql-server #sql-server-2008 #sql-server-2012 #sql-update

#sql #sql-сервер #sql-server-2008 #sql-server-2012 #sql-обновление

Вопрос:

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

Вот мой пример сценария

введите описание изображения здесь

Это должно быть ожидаемым результатом.

введите описание изображения здесь

Я не хочу также обновлять строки, которые уже имеют значения. Возможно ли это? Я не имею ни малейшего представления о том, как достичь этого результата. Кто-нибудь может мне помочь? Я использую SQL.

Спасибо

Комментарии:

1. Что вы подразумеваете под тем же первичным ключом. Первичный ключ не может быть одинаковым для 2 строк?

2. Извините за неправильное понимание моего примера. Я пытаюсь сказать, что первичным ключом для моего примера является столбец (ИДЕНТИФИКАТОР, ПОСЛЕДОВАТЕЛЬНОСТЬ). И должен обновить значение в том же диапазоне идентификаторов, что и пример выше

3. Понял. еще один вопрос, нужно ли всегда выбирать значение sequence 1 ?

Ответ №1:

Вы можете использовать оконные функции и обновляемый CTE.

Если есть только одно значение, не являющееся null значением per id , то достаточно минимального или максимального окна:

 with cte as (
    select value, min(value) over(partition by id) as new_value
    from mytable t
)
update cte set value = new_value where value is null
 

Если вам конкретно нужна строка, в которой sequence есть значение 1 , используйте агрегацию условного окна:

 with cte as (
    select value, 
        min(case when sequence = 1 then value end) over(partition by id) as new_value
    from mytable t
)
update cte set value = new_value where value is null
 

Наконец, если вам нужна строка с минимальным sequence значением, независимо от ее фактического значения:

 with cte as (
    select value, 
        first_value(value) over(partition by id order by sequence) as new_value
    from mytable t
)
update cte set value = new_value where value is null
 

Комментарии:

1. спасибо за ваш ответ @GMB, но извините за позднее уведомление.. Однако я обновляю свой вопрос. проблема в том, что я не хочу, чтобы существующие значения обновлялись

2. @davinceleecode: это не обновляет существующие значения — условие where value is null во внешнем запросе гарантирует, что обновляются только null значения.

Ответ №2:

Оконная функция DENSE_RANK удобна для этого типа последовательности. Если цель состоит в том, чтобы просто вернуть значение, нет необходимости сохранять его, поскольку его можно получить непосредственно в select.

 DECLARE @Test as Table (
    Id char(1),
    Seq int,
    Val varchar(10)
)

INSERT @Test (Id, Seq)
VALUES
    ('A','1'),
    ('A','2'),
    ('A','3'),
    ('A','4'),
    ('A','5'),
    ('B','1'),
    ('B','2'),
    ('B','3'),
    ('B','4'),
    ('C','4'),
    ('C','5');

-- Select Only

SELECT Id, Seq, 
    'Test'   LTRIM(STR(DENSE_RANK() OVER (ORDER BY Id))) as [Val]
FROM @Test

-- Update via derived table

UPDATE t
SET Val = 'Test'   LTRIM(STR(Seq2))
FROM @Test t
INNER JOIN (
    SELECT Id, Seq, DENSE_RANK() OVER (ORDER BY Id) as [Seq2]
    FROM @Test
) v
ON v.Id = t.Id AND v.Seq = t.Seq