#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