За обновленный вопрос
Я добавил предложение COALESCE()
, чтобы отследить случаи, когда не найдено подходящей альтернативы. И поместите вычисление значения по умолчанию в подзапрос для многократного использования.
UPDATE employees e
SET zipcode_mod =
CASE WHEN length(e.zipcode) > 2 THEN
COALESCE((
SELECT t.zip
FROM tmp_agg_zips t
WHERE substr(t.zipcode, 1, 3) = substr(e.zipcode, 1, 3)
ORDER BY t.emp_cnt DESC, t.zip -- lowest zip for mult. emp_cnt
LIMIT 1
), t0.zip)
ELSE
t0.zip
END
FROM (
SELECT zip
FROM tmp_agg_zips
ORDER BY emp_cnt DESC, t.zip
LIMIT 1
) t0
WHERE NOT EXISTS (
SELECT *
FROM ref_zips r
WHERE r.zip5 = e.zipcode
)
Для оригинального вопроса
Этот запрос работает с более ранними версиями PostgreSQL:
UPDATE employees e
SET zipcode_mod =
CASE WHEN length(e.zipcode) > 2 THEN (
SELECT t.zip
FROM tmp_agg_zips t
WHERE substr(t.zipcode, 1, 3) = substr(e.zipcode, 1, 3)
ORDER BY t.emp_cnt DESC, t.zip -- lowest zip for mult. emp_cnt
LIMIT 1
)
ELSE (
SELECT zip
FROM tmp_agg_zips
ORDER BY emp_cnt DESC, t.zip
LIMIT 1
)
END
WHERE NOT EXISTS (
SELECT *
FROM ref_zips r
WHERE r.zip5 = e.zipcode
)
В PostgreSQL 9.1 , CTE должен работать лучше:
WITH x AS (
SELECT zip
FROM tmp_agg_zips
ORDER BY emp_cnt DESC, t.zip
LIMIT 1
)
UPDATE employees e
SET zipcode_mod =
CASE WHEN length(e.zipcode) > 2 THEN (
SELECT t.zip
FROM tmp_agg_zips t
WHERE left(t.zipcode, 3) = left(e.zipcode, 3)
ORDER BY t.emp_cnt DESC, t.zip -- pick lowest zip
LIMIT 1
)
ELSE
x.zip
END
FROM x
WHERE NOT EXISTS (
SELECT *
FROM ref_zips r
WHERE r.zip5 = e.zipcode
)
Если в tmp_agg_zips
есть несколько строк с одинаковыми (самыми высокими) emp_cnt
, я выбираю «самые низкие» zip
. Вы не указали, как разорвать эти связи.
Кстати, разные имена столбцов для почтовых индексов мне не помогают. Таблица с именами столбцов делает работу лучше.