JGH предоставил умный способ UPDATE
нескольких столбцов одновременно из (коррелированного) подзапроса. Возможно с Postgres 9.5. Однако есть существенные недостатки.
Эта форма обновляет каждую строку в таблице безоговорочно . Вам придется повторить вычисление в предложении WHERE
, чтобы сделать его условно, что не соответствует цели сделать это только один раз.
В Postgr SQL модель MV CC модель UPDATE
По сути, это означает написание новой версии полной строки, таблицы с разбуханием и индексов. Само по себе дорого, но также требует много дополнительной работы для VACUUM
- и / или снижения производительности, если вы не можете или не убираете. См .:
Либо вы действительно хотите обновить каждую строку, тогда это в принципе нормально. Однако, если вы не связаны с одновременной загрузкой или внутренними ссылками на таблицу (представления, FK, ...), рассмотрите возможность написания новой таблицы. Обычно дешевле в целом.
Однако некоторые (или многие / большинство?) Строки могут быть уже устаревшими. Тогда это огромные отходы . Вместо этого рассмотрим:
UPDATE scratch.intersections AS i
SET legs = r.legs
, streets = r.streets
FROM scratch.intersections x
JOIN LATERAL (
SELECT count(*) AS legs -- assuming r.geom is NOT NULL
, array_agg(DISTINCT s.NAME ORDER BY s.NAME)
FILTER (WHERE s.NAME IS NOT NULL) AS streets
FROM received.streets s
WHERE ST_DWithin(x.geom, s.geom, 2)
) r ON x.legs IS DISTINCT FROM r.legs
OR x.streets IS DISTINCT FROM r.streets
WHERE i.id = x.id; -- id being the PK (or at least UNIQUE)
Это не касается строк, которые на самом деле не меняются.
Нам нужен дополнительный экземпляр scratch.intersections
в предложении FROM
, чтобы разрешить LATERAL
присоединиться. Но мы исключаем все строки без изменений перед применением обновления - таким образом, сохраняя большую часть работы для каждой строки, которая уже обновлена. Ну, так как подзапрос относительно дорогой, возможно, не большинство работы. Но обычно фактическая операция записи намного дороже, чем вычисление новых значений.
Это довольно близко к тому, что вы имели в виду в своем последнем абзаце. Но более эффективно, не создавая временную таблицу, и вы также сохраняете пустые записи.
И если вам нужно только обновить потенциально затронутые строки в intersections
после изменения нескольких строк в streets.geom
, есть больший потенциал оптимизации , еще. Не вдаваясь в подробности, кажется, выходит за рамки этого вопроса.
Связанный: