Проблема в том, что вам нужно работать со всем подзапросом как с одним набором, чтобы получить row_number
, чтобы получить нужный вам результат, но вам также нужно уменьшить этот набор до одной записи, чтобы обновить каждую строку. Хотя это абсолютно возможно с update
, гораздо проще использовать merge
в этом сценарии (при условии, что вы используете 10g):
MERGE INTO rptdata rp
USING (SELECT ROW_NUMBER() OVER (PARTITION BY rs1.c1, 0, rs1.c5, rs1.c3
ORDER BY rs1.c1, rs1.c5, rs1.c3 DESC) AS r
FROM rptdata rs1
WHERE rs1.program_name = 'INTERNAL'
AND rs1.program_id = 030911
AND (rs1.c6 IS NULL OR rs1.c8 IS NULL OR rs1.c9 IS NULL)
AND rs1.c28 IS NULL) rs
ON (rs.c1 = rp.c1 AND rs.c5 = rp.c5 AND rs.c3 = rp.c3)
WHEN MATCHED THEN
UPDATE SET
c98 = rs.r
WHERE program_name = 'INTERNAL'
AND program_id = 030911
AND (c6 IS NULL OR c8 IS NULL OR c9 IS NULL)
AND c28 IS NULL
Кстати, ваш запрос не так уж далек. Как указано выше, вам нужно получить весь набор с помощью row_number
, а затем отфильтровать отдельные записи, необходимые для каждой обновляемой строки. Для этого вам нужно переместить условия соединения во внешний запрос:
UPDATE rptdata
SET c98 =
(SELECT r
FROM (SELECT rs1.c1,
rs1.c5,
rs1.c3,
ROW_NUMBER() OVER (PARTITION BY rs1.c1, 0, rs1.c5, rs1.c3
ORDER BY rs1.c1, rs1.c5, rs1.c3 DESC)
AS r
FROM rptdata rs1
WHERE rs1.program_name = 'INTERNAL'
AND rs1.program_id = 030911
AND (rs1.c6 IS NULL OR rs1.c8 IS NULL OR rs1.c9 IS NULL)
AND rs1.c28 IS NULL)
WHERE rs1.c1 = c1 AND rs1.c5 = c5 AND rs1.c3 = c3)
WHERE program_name = 'INTERNAL'
AND program_id = 030911
AND (c6 IS NULL OR c8 IS NULL OR c9 IS NULL)
AND c28 IS NULL