gendesign/tradein-mvp/backend/scripts/audit_address_sample.sql
Light1YT 3c506222e6
All checks were successful
Deploy Trade-In / changes (push) Successful in 13s
Deploy Trade-In / build-backend (push) Successful in 23s
Deploy Trade-In / deploy (push) Successful in 36s
Deploy Trade-In / build-frontend (push) Has been skipped
feat(tradein): Phase 2-3 of #582 — Yandex backfill + canonical audit (#591)
2026-05-27 06:30:54 +00:00

47 lines
2 KiB
SQL

-- audit_address_sample.sql
-- Random sample of EKB houses for the address-mismatch audit (issue #582).
--
-- Strategy:
-- 1. Filter to houses with non-null lat/lon and non-empty address.
-- 2. Random shuffle via `ORDER BY random()` — repeatable enough for spot
-- sampling without needing a stable PRNG seed (the audit table dedupes
-- via UNIQUE (house_id, audit_batch), so re-running gives idempotent
-- results regardless of which rows land in the sample first).
-- 3. Cap the result at :limit_per_district * 8 rows — keeps the bind-param
-- contract compatible with the old stratified sampler (`:limit_per_district`
-- is still honored, just multiplied by the assumed 8-district count).
--
-- Why no spatial stratification anymore:
-- The previous version JOINed to `gendesign_ekb_districts_geom` (FDW
-- polygon table) to bucket houses by admin district. That join is fine on
-- prod where FDW is wired, but it adds a dependency we don't need for
-- Phase 2-3 (backfill + canonical reverse). Aggregation by district at
-- report time still works — we re-derive district during the audit via
-- spatial containment in the report SQL when needed.
--
-- Bind param:
-- :limit_per_district — kept for back-compat with the audit driver.
-- Effective sample size = :limit_per_district * 8 (e.g. 25 → 200).
--
-- Columns returned:
-- id, address, lat, lon, district
-- `district` is always NULL here — the audit driver will reverse-derive it
-- from Yandex Geocoder response (Yandex returns admin component) or leave
-- it NULL if not present in the response.
--
-- NB: uses CAST(:x AS int) per project sql.md rule (psycopg v3 ignores ::type
-- after bind params).
SELECT
h.id,
h.address,
h.lat,
h.lon,
NULL::text AS district
FROM houses h
WHERE h.lat IS NOT NULL
AND h.lon IS NOT NULL
AND h.address IS NOT NULL
AND length(trim(h.address)) > 0
ORDER BY random()
LIMIT CAST(:limit_per_district AS int) * 8;