From 2104ed879b431eef9f6fbfcf92afdb4fc7165a63 Mon Sep 17 00:00:00 2001 From: lekss361 Date: Sun, 17 May 2026 16:56:22 +0300 Subject: [PATCH] fix(sf-21b): weighted AVG in _INLINE_VELOCITY_SQL (best_layouts.py) Replace unweighted AVG(deals_total_avg_area_m2) and AVG(deals_total_avg_price_thousand_rub_per_m2) with SUM(x * count) / NULLIF(SUM(count), 0) pattern in _INLINE_VELOCITY_SQL. Months with zero deals no longer dilute the weighted mean 2-4x. P0 follow-up to PR #290 (mv fix, issue #21). --- backend/app/services/site_finder/best_layouts.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/backend/app/services/site_finder/best_layouts.py b/backend/app/services/site_finder/best_layouts.py index ee7d2105..14faf117 100644 --- a/backend/app/services/site_finder/best_layouts.py +++ b/backend/app/services/site_finder/best_layouts.py @@ -118,9 +118,16 @@ _INLINE_VELOCITY_SQL = text(""" ELSE crm.room_bucket END AS room_bucket, SUM(crm.deals_total_count) AS deals_window, - AVG(crm.deals_total_avg_area_m2) AS avg_area_m2, - AVG(crm.deals_total_avg_price_thousand_rub_per_m2) - * 1000.0 AS avg_price_per_m2_rub, + COALESCE( + SUM(crm.deals_total_avg_area_m2 * crm.deals_total_count) + / NULLIF(SUM(crm.deals_total_count), 0), + 0 + )::numeric(10, 2) AS avg_area_m2, + COALESCE( + SUM(crm.deals_total_avg_price_thousand_rub_per_m2 * crm.deals_total_count) + / NULLIF(SUM(crm.deals_total_count), 0), + 0 + )::numeric(12, 2) * 1000.0 AS avg_price_per_m2_rub, array_agg(DISTINCT cm.domrf_obj_id) AS competitor_obj_ids, COUNT(DISTINCT cm.domrf_obj_id) AS competitor_count, MIN(crm.report_month) AS window_start, -- 2.45.3