Sprint 4 implementation: Loaders: - base.py: Session management, bulk insert, upsert utilities - dimensions.py: Load time, district, zone, neighbourhood, policy dimensions - trreb.py: Load TRREB purchase data to fact_purchases - cmhc.py: Load CMHC rental data to fact_rentals dbt Project: - Project configuration (dbt_project.yml, packages.yml) - Staging models for all fact and dimension tables - Intermediate models with dimension enrichment - Marts: purchase analysis, rental analysis, market summary Closes #16 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
80 lines
1.9 KiB
SQL
80 lines
1.9 KiB
SQL
-- Mart: Toronto Purchase Market Analysis
|
|
-- Final analytical table for purchase/sales data visualization
|
|
-- Grain: One row per district per month
|
|
|
|
with purchases as (
|
|
select * from {{ ref('int_purchases__monthly') }}
|
|
),
|
|
|
|
-- Add year-over-year calculations
|
|
with_yoy as (
|
|
select
|
|
p.*,
|
|
|
|
-- Previous year same month values
|
|
lag(p.avg_price, 12) over (
|
|
partition by p.district_code
|
|
order by p.date_key
|
|
) as avg_price_prev_year,
|
|
|
|
lag(p.sales_count, 12) over (
|
|
partition by p.district_code
|
|
order by p.date_key
|
|
) as sales_count_prev_year,
|
|
|
|
lag(p.median_price, 12) over (
|
|
partition by p.district_code
|
|
order by p.date_key
|
|
) as median_price_prev_year
|
|
|
|
from purchases p
|
|
),
|
|
|
|
final as (
|
|
select
|
|
purchase_id,
|
|
date_key,
|
|
full_date,
|
|
year,
|
|
month,
|
|
quarter,
|
|
month_name,
|
|
district_key,
|
|
district_code,
|
|
district_name,
|
|
area_type,
|
|
sales_count,
|
|
dollar_volume,
|
|
avg_price,
|
|
median_price,
|
|
new_listings,
|
|
active_listings,
|
|
days_on_market,
|
|
sale_to_list_ratio,
|
|
absorption_rate,
|
|
months_of_inventory,
|
|
|
|
-- Year-over-year changes
|
|
case
|
|
when avg_price_prev_year > 0
|
|
then round(((avg_price - avg_price_prev_year) / avg_price_prev_year) * 100, 2)
|
|
else null
|
|
end as avg_price_yoy_pct,
|
|
|
|
case
|
|
when sales_count_prev_year > 0
|
|
then round(((sales_count - sales_count_prev_year)::numeric / sales_count_prev_year) * 100, 2)
|
|
else null
|
|
end as sales_count_yoy_pct,
|
|
|
|
case
|
|
when median_price_prev_year > 0
|
|
then round(((median_price - median_price_prev_year) / median_price_prev_year) * 100, 2)
|
|
else null
|
|
end as median_price_yoy_pct
|
|
|
|
from with_yoy
|
|
)
|
|
|
|
select * from final
|