fix(analytics): _district_market_saturation latest-snapshot filter (#1221)
domrf_kn_objects/sales_agg хранят ~3 snapshot'а на obj_id (weekly UPSERT, retention=none). JOIN без latest-фильтра считал каждый ЖК N раз: sold_median тянулся старыми perc → sat_factor занижен, гейт n>=5 проходил уже при 2 ЖК (n=6), sat_n завышен ~×N в scope. Сданные ЖК просачивались через старые снапшоты со статусом 'Строящиеся'. Patch: AND a.snapshot_date = (SELECT MAX(snapshot_date) FROM ...) для обеих таблиц (зеркало #1210/#1212). COUNT(*) → COUNT(DISTINCT a.obj_id) defensive. 29 recommend_mix + 8 saturation тестов зелёные. Closes #1221
This commit is contained in:
parent
d694e735cd
commit
780dd5640c
1 changed files with 16 additions and 1 deletions
|
|
@ -1414,12 +1414,21 @@ def _district_market_saturation(db: Session, *, district_name: str) -> tuple[flo
|
||||||
|
|
||||||
Возвращает (median_pct, n_objects). None если <5 ЖК с perc.
|
Возвращает (median_pct, n_objects). None если <5 ЖК с perc.
|
||||||
"""
|
"""
|
||||||
|
# #1221: domrf_kn_objects/domrf_kn_sales_agg хранят ~3 snapshot'а на obj_id
|
||||||
|
# (UNIQUE(obj_id,[type,]snapshot_date), weekly UPSERT, ретенции нет). Без
|
||||||
|
# latest-фильтра один ЖК входил в медиану N раз → sold_median тянется старыми
|
||||||
|
# perc (sold% растёт во времени → sat_factor занижен), гейт n>=5 проходил уже
|
||||||
|
# при 2 ЖК, sat_n завышен ~×N. Фильтруем оба JOIN-партнёра MAX(snapshot_date)
|
||||||
|
# (зеркало #1210/#1212, ср. строки 1200/1208 и latest_obj-CTE стр. ~2780
|
||||||
|
# «иначе comparables дублируются»). COUNT(DISTINCT a.obj_id) — defensive:
|
||||||
|
# после latest-snapshot пары (obj_id, type='apartments') уникальны, но явный
|
||||||
|
# DISTINCT исключает регрессию, если кто-то ослабит UNIQUE-constraint.
|
||||||
row = (
|
row = (
|
||||||
db.execute(
|
db.execute(
|
||||||
text(
|
text(
|
||||||
"""
|
"""
|
||||||
SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY a.perc) AS sold_median,
|
SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY a.perc) AS sold_median,
|
||||||
COUNT(*) AS n
|
COUNT(DISTINCT a.obj_id) AS n
|
||||||
FROM domrf_kn_sales_agg a
|
FROM domrf_kn_sales_agg a
|
||||||
JOIN domrf_kn_objects o
|
JOIN domrf_kn_objects o
|
||||||
ON o.obj_id = a.obj_id
|
ON o.obj_id = a.obj_id
|
||||||
|
|
@ -1428,6 +1437,12 @@ def _district_market_saturation(db: Session, *, district_name: str) -> tuple[flo
|
||||||
AND a.perc IS NOT NULL
|
AND a.perc IS NOT NULL
|
||||||
AND o.district_name = :dn
|
AND o.district_name = :dn
|
||||||
AND o.site_status = 'Строящиеся'
|
AND o.site_status = 'Строящиеся'
|
||||||
|
AND a.snapshot_date = (
|
||||||
|
SELECT MAX(snapshot_date) FROM domrf_kn_sales_agg
|
||||||
|
)
|
||||||
|
AND o.snapshot_date = (
|
||||||
|
SELECT MAX(snapshot_date) FROM domrf_kn_objects
|
||||||
|
)
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
{"dn": district_name},
|
{"dn": district_name},
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue