-- Дополнительные связи между таблицами (27.04.2026 evening) + analytical views -- для сквозного анализа: квартиры ↔ ЖК ↔ застройщики ↔ регионы. -- -- Pre-checked orphans: -- • domrf_kn_objects.region_cd → regions: 1516/1516 valid ✓ -- • domrf_kn_objects.dev_id → developers: 34 orphans (NULLed before FK) -- • sv_dev_sales.dev_id → developers: 50/50 valid ✓ -- • rosreestr_rent_deals.region_cd → regions: 1071/1071 valid ✓ -- • dev_growth.dev_id → developers: ALL NULL — no FK possible -- • domrf_kn_flats.obj_id → kn_objects.obj_id: ALL 27563 orphans -- (different ID systems: /api/kn/flats uses hobj_id-style codes, only -- 2 unique obj_id from flats match objects.hobj_id). NO FK; join only -- via obj_name text match (best-effort) or aggregate by obj_name. BEGIN; -- 1. NULL out 34 orphan dev_id values in kn_objects before adding FK UPDATE domrf_kn_objects SET dev_id=NULL WHERE dev_id IS NOT NULL AND NOT EXISTS (SELECT 1 FROM domrf_developers d WHERE d.developer_id=domrf_kn_objects.dev_id); -- 2. Add 4 clean FKs (31 → 35 total) ALTER TABLE domrf_kn_objects ADD CONSTRAINT fk_kn_obj_region FOREIGN KEY (region_cd) REFERENCES domrf_regions(region_id) ON UPDATE CASCADE, ADD CONSTRAINT fk_kn_obj_developer FOREIGN KEY (dev_id) REFERENCES domrf_developers(developer_id) ON UPDATE CASCADE; ALTER TABLE sv_dev_sales ADD CONSTRAINT fk_sv_dev_sales_developer FOREIGN KEY (dev_id) REFERENCES domrf_developers(developer_id) ON UPDATE CASCADE; ALTER TABLE rosreestr_rent_deals ADD CONSTRAINT fk_rent_deals_region FOREIGN KEY (region_cd) REFERENCES domrf_regions(region_id) ON UPDATE CASCADE; -- 3. Analytical view: ЖК + dev + регион (use FK joins) CREATE OR REPLACE VIEW v_jk_with_developer AS SELECT o.obj_id, o.hobj_id, o.comm_name AS jk_name, o.addr, o.short_addr, o.region_cd, r.region_name, o.dev_id, COALESCE(d.developer_name, o.dev_name) AS dev_name, o.flat_count, o.square_living, o.obj_class, o.wall_type, o.energy_eff, o.escrow, o.green_house, o.ready_dt, o.site_status, o.is_prinzip, o.is_ekb, o.is_problem, o.latitude, o.longitude FROM domrf_kn_objects o LEFT JOIN domrf_developers d ON o.dev_id = d.developer_id LEFT JOIN domrf_regions r ON o.region_cd = r.region_id; COMMENT ON VIEW v_jk_with_developer IS 'ЖК Свердл с обогащением dev_name из канонического справочника + region_name. Использует FK fk_kn_obj_developer/region.'; -- 4. ЖК + поквартирные продажи (text match obj_name → only 2 ЖК matchятся, -- но view удобен для standalone-анализа kn_flats по ЖК). CREATE OR REPLACE VIEW v_jk_sales_summary AS SELECT obj_name AS jk_name, MIN(city) AS city, COUNT(*) AS flats_total, COUNT(*) FILTER (WHERE status='sold') AS flats_sold, COUNT(*) FILTER (WHERE status='booked') AS flats_booked, COUNT(*) FILTER (WHERE status='free') AS flats_free, ROUND((COUNT(*) FILTER (WHERE status='sold') * 100.0 / NULLIF(COUNT(*),0))::numeric, 1) AS sold_pct, ROUND(AVG(price_per_m2)::numeric, 0) AS avg_ppm, ROUND(AVG(total_area)::numeric, 1) AS avg_area_sqm, SUM(price_rub) AS total_value_rub FROM domrf_kn_flats WHERE obj_name IS NOT NULL GROUP BY obj_name; COMMENT ON VIEW v_jk_sales_summary IS 'Поквартирная агрегация по ЖК (имя): кол-во × free/booked/sold + avg цена/площадь. Источник: domrf_kn_flats (РФ-snapshot).'; -- 5. Портфель ЖК у каждого девелопера (через FK) CREATE OR REPLACE VIEW v_developer_portfolio AS SELECT d.developer_id, d.developer_name, COUNT(DISTINCT o.obj_id) AS jk_count, SUM(o.flat_count) AS jk_flats_total, ROUND(SUM(o.square_living)::numeric, 0) AS jk_sqm_total, COUNT(DISTINCT o.obj_id) FILTER (WHERE o.is_ekb=true) AS jk_ekb, COUNT(DISTINCT o.obj_id) FILTER (WHERE o.is_problem=true) AS jk_problem, COUNT(DISTINCT o.obj_id) FILTER (WHERE o.escrow=true) AS jk_escrow, COUNT(DISTINCT o.obj_id) FILTER (WHERE o.site_status='Сданные') AS jk_completed, COUNT(DISTINCT o.obj_id) FILTER (WHERE o.site_status='Строящиеся') AS jk_in_progress, MIN(o.ready_dt) AS earliest_ready, MAX(o.ready_dt) AS latest_ready FROM domrf_developers d LEFT JOIN domrf_kn_objects o ON o.dev_id = d.developer_id GROUP BY d.developer_id, d.developer_name; COMMENT ON VIEW v_developer_portfolio IS 'Портфель ЖК у каждого девелопера: total ЖК / квартир / м² + разбивка ЕКБ / problem / эскроу / Сданы/Строятся. Только Свердл (что в kn_objects).'; -- 6. Полный профиль девелопера = portfolio + квартирография + realization Свердл CREATE OR REPLACE VIEW v_developer_full_metrics AS SELECT p.developer_id, p.developer_name, p.jk_count, p.jk_flats_total, p.jk_sqm_total, p.jk_ekb, p.jk_completed, p.jk_in_progress, p.jk_escrow, da_total.flat_count AS agg_flats_total, da_one.flat_count AS agg_one_room, da_two.flat_count AS agg_two_room, da_three.flat_count AS agg_three_room, da_four.flat_count AS agg_four_plus, ROUND((da_one.flat_count * 100.0 / NULLIF(da_total.flat_count,0))::numeric, 1) AS pct_one, ROUND(((COALESCE(da_three.flat_count,0) + COALESCE(da_four.flat_count,0)) * 100.0 / NULLIF(da_total.flat_count,0))::numeric, 1) AS pct_three_plus, ROUND((da_total.area_sqm / NULLIF(da_total.flat_count,0))::numeric, 1) AS avg_area_sqm, rl.total_square AS sverdl_sqm, rl.sold_perc AS sverdl_sold_pct, rl.unsold_perc AS sverdl_unsold_pct, rl.price_avg AS sverdl_price_avg FROM v_developer_portfolio p LEFT JOIN domrf_developer_aggregates da_total ON da_total.developer_id=p.developer_id AND da_total.room_count_type='TOTAL' AND da_total.region_id=0 LEFT JOIN domrf_developer_aggregates da_one ON da_one.developer_id=p.developer_id AND da_one.room_count_type='ONE' AND da_one.region_id=0 LEFT JOIN domrf_developer_aggregates da_two ON da_two.developer_id=p.developer_id AND da_two.room_count_type='TWO' AND da_two.region_id=0 LEFT JOIN domrf_developer_aggregates da_three ON da_three.developer_id=p.developer_id AND da_three.room_count_type='THREE'AND da_three.region_id=0 LEFT JOIN domrf_developer_aggregates da_four ON da_four.developer_id=p.developer_id AND da_four.room_count_type='FOUR' AND da_four.region_id=0 LEFT JOIN domrf_realization rl ON rl.subject=p.developer_id AND rl.endpoint_type='developer' AND rl.region_code=66 AND rl.type_square='total' AND rl.snapshot_date='2026-04-27'; COMMENT ON VIEW v_developer_full_metrics IS 'Единый профиль девелопера: portfolio (ЖК) + квартирография (1-к/2-к/3-к доли) + realization Свердл. Best query для PRINZIP/Брусника/конкурентов сравнения.'; COMMIT;