Merge pull request 'fix(sql): v_supply_layers_latest keep dev_group_name in DISTINCT ON key (#1650)' (#1688) from fix/supply-view-devgroup-key-1650 into main
Some checks are pending
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Waiting to run
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Some checks are pending
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Waiting to run
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
This commit is contained in:
commit
7d8d12f5a6
1 changed files with 80 additions and 0 deletions
80
data/sql/161_supply_layers_view_devgroup_key.sql
Normal file
80
data/sql/161_supply_layers_view_devgroup_key.sql
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
-- 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;
|
||||||
Loading…
Add table
Reference in a new issue