#sql #sql-server
#sql #sql-сервер
Вопрос:
У меня есть следующее обновление, которое обновляет запись на основе предыдущей записи —
WITH CTE AS(
SELECT
patient,
start,
CASE
WHEN
ISNULL(start, '') = ''
AND cd = '3'
AND LAG([thru_dt]) OVER (PARTITION BY [patient] ORDER BY cast(claimno AS int) ASC) BETWEEN CONVERT(VARCHAR, DATEADD(DAY, -30, thru_dt), 112) AND thru_dt
AND LAG([cd]) OVER (PARTITION BY [patient] ORDER BY cast(claimno AS int) ASC) = '30'
THEN LAG([start]) OVER (PARTITION BY [patient] ORDER BY cast(claimno AS int) ASC)
WHEN ISNULL(hhstrtdt, '') = '' AND
ROW_NUMBER() OVER(PARTITION BY patient ORDER BY cast(claimno AS int) DESC) = 1
AND LAG([cd]) OVER (PARTITION BY [patient] ORDER BY cast(claimno AS int) ASC) = '30'
AND LAG([thru_dt]) OVER (PARTITION BY [patient] ORDER BY cast(claimno AS int) ASC) BETWEEN CONVERT(VARCHAR, DATEADD(DAY, -30, thru_dt), 112) AND thru_dt
THEN LAG([start]) OVER (PARTITION BY [patient] ORDER BY cast(claimno AS int) ASC)
ELSE start
END AS new_start
FROM table
)
UPDATE CTE
SET start = new_start
Этот запрос обновляет только одну запись за раз. Например, если бы у меня был этот ввод —
start patient cd
20190307 497863693 30
NULL 497863693 30
NULL 497863693 30
NULL 497863693 30
Чтобы обновить все 3 строки с нулевым start
значением со значением первой строки, мне пришлось бы выполнить запрос 3 раза.
Вывод будет —
start patient cd
20190307 497863693 30
20190307 497863693 30
20190307 497863693 30
20190307 497863693 30
Есть ли способ заставить запрос обновлять все строки для вышеупомянутого пациента вместо того, чтобы делать это по одному? Я мог бы вести подсчет нулей в таблице и прекратить выполнение обновления, как только количество нулей в таблице перестанет уменьшаться, но это не кажется хорошим способом сделать это.
Комментарии:
1. Используйте
max()
вместо этого с тем же разделом и упорядочивайте по2. Я не думаю, что смогу использовать MAX(). Мне нужно, чтобы текущая запись rows была предыдущей записью rows. @Sujitmohanty30
3. Из вашего примера, похоже, что это не разные значения, если я использую
lag
илиmax
. В любом случае, это мое понимание на данный момент. Было бы неплохо, если бы вы предоставили фактические данные выборки вместо вывода запроса, а затем, по крайней мере, два разных сценария, что обновлять в качестве ожидаемого результата.4. @Doe . . . Примеры данных, желаемые результаты и четкое объяснение логики были бы полезны. Ваш запрос не соответствует образцу данных.
5. вы ищете последнее значение, отличное от NULL ?
Ответ №1:
Для этого можно использовать накопительный максимум. Если я правильно понимаю, вы хотите сбросить NULL
значения в строках с cd = 30 до последнего start
значения, когда cd = '30'
:
with toupdate as (
select t.*,
max(start) over (partition by patientid order by cast(claimno AS int)) as imputed_start
from t
where cd = '30'
)
update toupdate
set start = imputed_start
where start is null or imputed_start <> start;
Ответ №2:
Я думаю, что самый простой способ обновить всю таблицу сразу был бы примерно таким
with rn_cte as (
select * , row_number() over (partition by patient order by (select null)) rn
from tTable)
update tTable
set start=NULl
where rn>=2;