-- Fix trend_windows to upsert instead of accumulating rows. -- Add unique constraint so ON CONFLICT works, then deduplicate existing data. -- Step 1: Keep only the most recent row per (entity_type, entity_id, window) DELETE FROM trend_windows WHERE id NOT IN ( SELECT DISTINCT ON (entity_type, entity_id, "window") id FROM trend_windows ORDER BY entity_type, entity_id, "window", generated_at DESC ); -- Step 2: Add unique constraint for upsert CREATE UNIQUE INDEX IF NOT EXISTS idx_trend_windows_entity_window ON trend_windows (entity_type, entity_id, "window"); -- Step 3: Clean up old competitive signal records (keep last 30 days) DELETE FROM competitive_signal_records WHERE computed_at < NOW() - INTERVAL '30 days'; -- Step 4: Add a partial index to speed up the NOT EXISTS check in the -- aggregation propagation query CREATE INDEX IF NOT EXISTS idx_competitive_signals_source_doc_ticker ON competitive_signal_records (source_document_id, source_ticker);