-- ============================================================================= -- QWHPI — Quebec Weekly Housing Price Index -- Author : Simon-Pierre Boucher -- Contact : contact@spboucher.ai -- File : db/schema.sql -- Purpose : Relational schema serving the API (loaded by engine export.py). -- ============================================================================= CREATE TABLE IF NOT EXISTS geographies ( geography_id TEXT PRIMARY KEY, geography_name TEXT NOT NULL, geography_level TEXT NOT NULL CHECK (geography_level IN ('province','region','municipality')), parent_id TEXT REFERENCES geographies(geography_id) ); CREATE TABLE IF NOT EXISTS series ( series_id TEXT PRIMARY KEY, -- ':' geography_id TEXT NOT NULL REFERENCES geographies(geography_id), property_type TEXT NOT NULL CHECK (property_type IN ('all','unifamilial','condo','plex')), base_period TEXT NOT NULL DEFAULT '2021 average = 100', UNIQUE (geography_id, property_type) ); CREATE TABLE IF NOT EXISTS model_runs ( run_id SERIAL PRIMARY KEY, model_version TEXT NOT NULL, data_vintage DATE NOT NULL, input_row_count BIGINT, input_hash TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), UNIQUE (model_version, data_vintage) ); CREATE TABLE IF NOT EXISTS observations ( series_id TEXT NOT NULL REFERENCES series(series_id), week DATE NOT NULL, index DOUBLE PRECISION, index_smoothed DOUBLE PRECISION NOT NULL, representative_value DOUBLE PRECISION, transactions INTEGER NOT NULL, effective_sample_size DOUBLE PRECISION, weekly_pct DOUBLE PRECISION, four_week_pct DOUBLE PRECISION, thirteen_week_pct DOUBLE PRECISION, twenty_six_week_pct DOUBLE PRECISION, yoy_pct DOUBLE PRECISION, lower_95 DOUBLE PRECISION NOT NULL, upper_95 DOUBLE PRECISION NOT NULL, reliability_grade CHAR(1) NOT NULL CHECK (reliability_grade IN ('A','B','C','D','E')), shrinkage_weight DOUBLE PRECISION, is_partial_week BOOLEAN NOT NULL DEFAULT FALSE, model_version TEXT NOT NULL, data_vintage DATE NOT NULL, PRIMARY KEY (series_id, week) ); CREATE INDEX IF NOT EXISTS idx_obs_week ON observations (week); CREATE TABLE IF NOT EXISTS liquidity ( series_id TEXT NOT NULL REFERENCES series(series_id), week DATE NOT NULL, transactions INTEGER NOT NULL, PRIMARY KEY (series_id, week) ); CREATE TABLE IF NOT EXISTS vintages ( series_id TEXT NOT NULL REFERENCES series(series_id), week DATE NOT NULL, first_release_index DOUBLE PRECISION, first_release_index_smoothed DOUBLE PRECISION NOT NULL, first_release_vintage DATE NOT NULL, PRIMARY KEY (series_id, week) ); -- Author credit: Simon-Pierre Boucher — contact@spboucher.ai