# Tecnica di generazione del SQL finale Adattata dallo step "query generation" di AV-SQL (divide-and-conquer ricorsivo) e dalla sua checklist di revisione. ## Generazione (divide-and-conquer) 1. **Dividi**: scomponi la domanda riscritta in sotto-domande, ognuna mirata a un pezzo di informazione o logica (una popolazione, un filtro, un aggregato). 2. **Conquista**: per ogni sotto-domanda formula uno pseudo-SQL, con segnaposto per le sotto-domande non ancora risolte. I CTE gia' testati in Fase 6 sono i mattoni preferenziali: riusali per nome, col loro esito noto. 3. **Ricombina**: sostituisci i segnaposto dal basso verso l'alto fino al SQL completo. Il SQL finale puo' includere i CTE nel proprio WITH. 4. Dialetto: PostgreSQL. Copia ESATTAMENTE i nomi di tabelle e colonne dal contesto schema; mai inventare oggetti. Il file `sessions//sql_final.sql` deve contenere SOLO il SQL, pulito e copiabile: niente commenti di razionale (quello vive negli artefatti di audit). ## Dimensione tempo (analisi per anno/mese/trimestre) Le fact table hanno `data_time_key` (`integer`, formato `YYYYMMDD`): è la FK verso `dim_time.day_key`. **Questa FK non è dichiarata** nel DWH (le fact hanno `foreign_keys: []`), quindi non comparirà in `schema_linking.json`: vai aggiunta a mano nel join. - Per estrarre anno, mese, trimestre, semestre ecc. fai `JOIN dim_time dt ON dt.day_key = .data_time_key` e usa le colonne della dimensione: `dt.year`, `dt.month`, `dt.quarter`, `dt.semester`, `dt.full_date`, `dt.month_name_it`, `dt.year_month`. - **Non** fare aritmetica sulla chiave (es. `data_time_key / 10000` per l'anno): funziona per caso ma è fragile e si rompe appena serve formattare una data o fare cast. Usa sempre `dim_time`. - "Ultimi N anni dall'anno più recente": `dt.year >= (SELECT MAX(year) FROM dim_time WHERE day_key IN (SELECT data_time_key FROM )) - (N-1)`, oppure calcola il max anno sulle righe effettivamente presenti nella fact. ## Checklist di revisione (su errori o risultati sospetti) - Le colonne restituite rispondono esattamente alla domanda? - I filtri (WHERE/HAVING) riflettono tutte le condizioni della domanda riscritta? - Aggregazioni, raggruppamenti e ordinamenti sono quelli richiesti? - Risultato vuoto o zero: quasi sempre indica un problema in condizioni o join. Verifica i valori dei filtri con `tht search ""` (match sui valori reali). - I join seguono quelli promossi in schema_linking.json? (eccezione: la FK `data_time_key → dim_time.day_key` non è dichiarata, vedi sezione tempo.) - Analisi temporali: stai usando `JOIN dim_time` e non aritmetica sulla chiave? Ogni revisione sostanziale va registrata con: `reviewer_decide(options:[{label:"Registra revisione", type:"sql_revised", subject:"sql_final", detail:"", rationale:""}], allow_other:false)`.