UPDATE FROM в PostgreSQL: сначала сделайте источник однозначным
Допустим, нужно перенести согласованные цены из staging в рабочий каталог. В staging осталось две версии цены одного товара: поставщик отправил исправление, а загрузчик сохранил обе строки. Обычный SELECT с JOIN показывает две строки, но UPDATE изменяет товар один раз. Какую именно цену получит каталог?
В UPDATE FROM одна целевая строка должна сопоставляться максимум с одной строкой источника. Если совпадений несколько, PostgreSQL использует одно из них; строить бизнес-правило на выборе такой строки нельзя. ORDER BY в отдельном просмотре staging этого отношения не меняет.
Как изменить решение
WITH ranked AS (
SELECT product_id, price,
row_number() OVER (
PARTITION BY product_id
ORDER BY version DESC, import_id DESC
) AS rn
FROM price_stage
)
UPDATE products AS p
SET price = r.price
FROM ranked AS r
WHERE r.rn = 1 AND r.product_id = p.id
RETURNING p.id, p.price;Для товара с версиями 4 и 5 будет выбрана версия 5. Если версия совпала, решение определит import_id. Этот столбец должен иметь согласованный смысл: например, уникальный номер принятой поставки. Случайный порядок строк в файле таким правилом не становится.
Дедупликацию лучше вынести в отдельный этап загрузки. Тогда можно сохранить отвергнутые версии, объяснить изменение цены и проверить результат до записи. Если по контракту два значения одного ключа недопустимы, вместо ранжирования нужна ошибка и уникальное ограничение в подготовленной таблице.
Что проверить на своих данных
Перед обновлением выполните SELECT product_id, count(*) FROM price_stage GROUP BY product_id HAVING count(*) > 1. Затем добавьте в тест две строки одной версии и проверьте правило разрешения ничьей. После UPDATE сверяйте сами пары товар–цена, а не только число затронутых строк.
Отдельно решите, что означает отсутствующая цена. NULL в новой версии может отменять цену или означать, что поле не прислали. COALESCE автоматически выберет вторую трактовку и способен скрыть корректное обнуление. Правило версий определяет победившую запись; правило пустых полей определяет её применение. Их полезно проверять разными примерами.
Практика дальше
После однозначного обновления цен следующая задача — встроить его в воспроизводимую загрузку. На Data Engineering Fast-Track вы собираете конвейер Kafka → Spark → Lakehouse под управлением Airflow: с контрактами данных, расписанием и backfill. Так подготовка источника становится частью пайплайна, который можно повторить после сбоя.
Посмотреть программу и практику курса
Источник: UPDATE FROM в PostgreSQL — официальная документация.
Другие задачи по теме: PostgreSQL: запись, блокировки и планы запросов.
Продолжить на практике
- Data Engineering Fast‑Track: Kafka → Airflow → Spark ↗
Практический fast-track по data engineering: за 4–6 недель собираем рабочий конвейер Kafka → Spark → Lakehouse под управлением Airflow. Разберём batch и streaming, окна и watermark, схемы и контракты. Мини‑проекты, Docker Compose, шаблоны DAG и пайплайнов. Курс подойдёт инженерам, аналитикам и тем, кто хочет освоить современные пайплайны данных с уверенным Python.
