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