gendesign/data/sql/45_relations_v2.sql
2026-04-27 13:05:36 +03:00

130 lines
7 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.

-- Дополнительные связи между таблицами (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;