gendesign/data/sql/161_supply_layers_view_devgroup_key.sql
bot-backend 986514be3e
Some checks failed
CI / changes (push) Successful in 8s
CI / changes (pull_request) Successful in 7s
CI / backend-tests (push) Has been skipped
CI / frontend-tests (push) Has been skipped
CI / openapi-codegen-check (push) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m43s
CI / backend-tests (pull_request) Failing after 8m50s
fix(sql): v_supply_layers_latest keep dev_group_name in DISTINCT ON key (#1650)
2026-06-17 20:37:46 +03:00

80 lines
5 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 161_supply_layers_view_devgroup_key.sql
-- #1650 — v_supply_layers_latest collapses L3 dev_groups: fix DISTINCT ON key.
--
-- БАГ: v_supply_layers_latest (м.125) использует DISTINCT ON по 6-колоночному ключу
-- (layer, district_name, complex_id, obj_class, source) — без dev_group_name.
-- После м.128 логический UNIQUE-ключ supply_layers расширен до 7 колонок:
-- (layer, district_name, complex_id, obj_class, dev_group_name, source, snapshot_date).
-- Для L3 (layer=3, domrf_multiphase): complex_id=NULL у ВСЕХ строк, разные dev_group'ы
-- района имеют одинаковый 6-column DISTINCT-ключ → VIEW схлопывает их в 1 строку.
-- Измерено на prod: 8 L3 строк в view (по 1 на район) vs 102 фактических строк в таблице.
-- Например, Академический: view→1 строка (607 юнитов), таблица→48 строк (41 887 юнитов).
--
-- ЧИНИМ: добавляем dev_group_name в DISTINCT ON / ORDER BY view'а.
-- Новый DISTINCT ON ключ:
-- (layer, district_name, complex_id, obj_class, dev_group_name, source)
-- зеркалит логический ключ uq_supply_layers_logical (м.128, без snapshot_date — view
-- берёт max-снапшот, snapshot_date остаётся в ORDER BY как tiebreak).
--
-- Зависимости:
-- • supply_layers (м.125 + м.128) — таблица с колонкой dev_group_name (м.128 обязателен).
-- • v_supply_layers_latest (м.125) — пересоздаётся здесь через CREATE OR REPLACE VIEW.
-- • Проверено: у v_supply_layers_latest нет downstream-зависимых view/matview.
-- CREATE OR REPLACE VIEW безопасен — колонки совместимы (добавляем dev_group_name в конец,
-- существующие колонки 1-13 не переупорядочиваем).
--
-- Idempotent: CREATE OR REPLACE VIEW — повторный прогон перезаписывает view тем же DDL,
-- без ошибок.
-- Deploy: auto-applied через _schema_migrations (ровно один раз по NN).
-- Migration order: м.125 и м.128 уже применены на prod — этот файл идёт ПОСЛЕ них.
-- После применения v_supply_layers_latest сразу вернёт корректные L3 per-dev_group строки
-- без перезапуска воркера (view читает актуальные данные supply_layers напрямую).
BEGIN;
-- ── Пересоздать v_supply_layers_latest с dev_group_name в DISTINCT ON ─────────────
-- Ключ: (layer, district_name, complex_id, obj_class, dev_group_name, source)
-- зеркалит uq_supply_layers_logical (м.128). DISTINCT ON требует совпадения ведущих
-- ORDER BY-выражений с DISTINCT-ключом — они перечислены первыми, далее snapshot_date
-- DESC, computed_at DESC, id DESC как детерминированный tiebreak на max-снапшот.
-- dev_group_name добавлена в SELECT как последняя колонка (позиция 14) — CREATE OR REPLACE
-- VIEW в PG допускает добавление колонок в конец списка без пересоздания зависимостей.
-- NULLS NOT DISTINCT логика: view просто делает DISTINCT ON, не UNIQUE-constraint —
-- NULL в dev_group_name у L1/L2 работает как обычный NULL в DISTINCT ON (все L1/L2 строки
-- с dev_group_name=NULL дедуплируются по остальным ключевым полям, что корректно).
CREATE OR REPLACE VIEW v_supply_layers_latest AS
SELECT DISTINCT ON (layer, district_name, complex_id, obj_class, dev_group_name, source)
id,
layer,
district_name,
complex_id,
obj_class,
units_estimate,
area_estimate,
expected_online_date,
source,
confidence,
method,
snapshot_date,
computed_at,
dev_group_name
FROM supply_layers
ORDER BY
layer,
district_name,
complex_id,
obj_class,
dev_group_name,
source,
snapshot_date DESC,
computed_at DESC,
id DESC;
COMMENT ON VIEW v_supply_layers_latest IS
'Свежий снапшот supply_layers на логический ключ (layer, district_name, complex_id, '
'obj_class, dev_group_name, source) — max(snapshot_date), детерминир. tiebreak '
'computed_at→id DESC. dev_group_name добавлен в DISTINCT ON в м.161 (#1650): '
'без него L3 dev_group''ы района схлопывались в 1 строку (~95.6% потерь). '
'Canonical read-path для future-supply (#950 Step6) и UI/forecast.';
COMMIT;