feat: expand dbt models
This commit is contained in:
@@ -18,5 +18,7 @@ models:
|
|||||||
data_platform:
|
data_platform:
|
||||||
staging:
|
staging:
|
||||||
+materialized: view
|
+materialized: view
|
||||||
|
intermediate:
|
||||||
|
+materialized: view
|
||||||
marts:
|
marts:
|
||||||
+materialized: table
|
+materialized: table
|
||||||
|
|||||||
47
dbt/models/intermediate/int_funda_listings_enriched.sql
Normal file
47
dbt/models/intermediate/int_funda_listings_enriched.sql
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
-- Intermediate model: enrich each listing with its most recent asking price
|
||||||
|
-- and the last recorded sold price from the price history.
|
||||||
|
|
||||||
|
with listings as (
|
||||||
|
select * from {{ ref('stg_funda_listings') }}
|
||||||
|
),
|
||||||
|
|
||||||
|
price_history as (
|
||||||
|
select * from {{ ref('stg_funda_price_history') }}
|
||||||
|
),
|
||||||
|
|
||||||
|
latest_asking as (
|
||||||
|
select distinct on (global_id)
|
||||||
|
global_id,
|
||||||
|
price as latest_asking_price,
|
||||||
|
price_date as latest_asking_date
|
||||||
|
from price_history
|
||||||
|
where
|
||||||
|
price_source = 'Funda'
|
||||||
|
and price_status = 'asking_price'
|
||||||
|
order by global_id asc, price_date desc
|
||||||
|
),
|
||||||
|
|
||||||
|
latest_sold as (
|
||||||
|
select distinct on (global_id)
|
||||||
|
global_id,
|
||||||
|
price as sold_price,
|
||||||
|
price_date as sold_date
|
||||||
|
from price_history
|
||||||
|
where price_status = 'sold'
|
||||||
|
order by global_id asc, price_date desc
|
||||||
|
),
|
||||||
|
|
||||||
|
enriched as (
|
||||||
|
select
|
||||||
|
l.*,
|
||||||
|
la.latest_asking_price,
|
||||||
|
la.latest_asking_date,
|
||||||
|
ls.sold_price,
|
||||||
|
ls.sold_date,
|
||||||
|
ls.sold_price is not null as is_sold
|
||||||
|
from listings as l
|
||||||
|
left join latest_asking as la on l.global_id = la.global_id
|
||||||
|
left join latest_sold as ls on l.global_id = ls.global_id
|
||||||
|
)
|
||||||
|
|
||||||
|
select * from enriched
|
||||||
26
dbt/models/intermediate/int_funda_listings_enriched.yml
Normal file
26
dbt/models/intermediate/int_funda_listings_enriched.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
models:
|
||||||
|
- name: int_funda_listings_enriched
|
||||||
|
description: >
|
||||||
|
Listings joined with the most recent asking price and last sold price from price history. One
|
||||||
|
row per listing.
|
||||||
|
meta:
|
||||||
|
dagster:
|
||||||
|
group: funda
|
||||||
|
columns:
|
||||||
|
- name: global_id
|
||||||
|
description: Funda internal listing ID.
|
||||||
|
tests:
|
||||||
|
- unique
|
||||||
|
- not_null
|
||||||
|
- name: latest_asking_price
|
||||||
|
description: Most recent asking price from Funda price history.
|
||||||
|
- name: latest_asking_date
|
||||||
|
description: Date of the most recent asking price event.
|
||||||
|
- name: sold_price
|
||||||
|
description: Price at which the listing was sold, if applicable.
|
||||||
|
- name: sold_date
|
||||||
|
description: Date the listing was sold, if applicable.
|
||||||
|
- name: is_sold
|
||||||
|
description: True when a sold price event exists for this listing.
|
||||||
29
dbt/models/marts/funda_city_stats.sql
Normal file
29
dbt/models/marts/funda_city_stats.sql
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
-- Mart: per-city price statistics for available listings.
|
||||||
|
|
||||||
|
with listings as (
|
||||||
|
select * from {{ ref('funda_listings') }}
|
||||||
|
where not is_sold
|
||||||
|
),
|
||||||
|
|
||||||
|
city_stats as (
|
||||||
|
select
|
||||||
|
city,
|
||||||
|
province,
|
||||||
|
offering_type,
|
||||||
|
object_type,
|
||||||
|
count(*) as listing_count,
|
||||||
|
round(avg(current_price), 0) as avg_price,
|
||||||
|
min(current_price) as min_price,
|
||||||
|
max(current_price) as max_price,
|
||||||
|
percentile_cont(0.5) within group (
|
||||||
|
order by current_price
|
||||||
|
) as median_price,
|
||||||
|
round(avg(price_per_sqm), 0) as avg_price_per_sqm,
|
||||||
|
round(avg(living_area), 0) as avg_living_area,
|
||||||
|
round(avg(bedrooms), 1) as avg_bedrooms
|
||||||
|
from listings
|
||||||
|
where current_price is not null
|
||||||
|
group by city, province, offering_type, object_type
|
||||||
|
)
|
||||||
|
|
||||||
|
select * from city_stats
|
||||||
69
dbt/models/marts/funda_listings.sql
Normal file
69
dbt/models/marts/funda_listings.sql
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
-- Mart: analysis-ready Funda listings table.
|
||||||
|
-- Selects the most useful fields and adds derived metrics.
|
||||||
|
|
||||||
|
with enriched as (
|
||||||
|
select * from {{ ref('int_funda_listings_enriched') }}
|
||||||
|
),
|
||||||
|
|
||||||
|
final as (
|
||||||
|
select
|
||||||
|
-- identifiers
|
||||||
|
global_id,
|
||||||
|
tiny_id,
|
||||||
|
url,
|
||||||
|
|
||||||
|
-- location
|
||||||
|
title,
|
||||||
|
city,
|
||||||
|
postcode,
|
||||||
|
province,
|
||||||
|
neighbourhood,
|
||||||
|
municipality,
|
||||||
|
latitude,
|
||||||
|
longitude,
|
||||||
|
|
||||||
|
-- property characteristics
|
||||||
|
object_type,
|
||||||
|
house_type,
|
||||||
|
offering_type,
|
||||||
|
construction_type,
|
||||||
|
construction_year,
|
||||||
|
energy_label,
|
||||||
|
living_area,
|
||||||
|
plot_area,
|
||||||
|
bedrooms,
|
||||||
|
rooms,
|
||||||
|
has_garden,
|
||||||
|
has_balcony,
|
||||||
|
has_solar_panels,
|
||||||
|
has_heat_pump,
|
||||||
|
has_roof_terrace,
|
||||||
|
is_energy_efficient,
|
||||||
|
is_monument,
|
||||||
|
|
||||||
|
-- pricing
|
||||||
|
price as current_price,
|
||||||
|
latest_asking_price,
|
||||||
|
latest_asking_date,
|
||||||
|
sold_price,
|
||||||
|
sold_date,
|
||||||
|
is_sold,
|
||||||
|
|
||||||
|
-- derived
|
||||||
|
photo_count,
|
||||||
|
|
||||||
|
-- engagement
|
||||||
|
views,
|
||||||
|
saves,
|
||||||
|
status,
|
||||||
|
|
||||||
|
-- meta
|
||||||
|
publication_date,
|
||||||
|
ingested_at,
|
||||||
|
case
|
||||||
|
when living_area > 0 then round(price::numeric / living_area, 0)
|
||||||
|
end as price_per_sqm
|
||||||
|
from enriched
|
||||||
|
)
|
||||||
|
|
||||||
|
select * from final
|
||||||
47
dbt/models/marts/funda_listings.yml
Normal file
47
dbt/models/marts/funda_listings.yml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
models:
|
||||||
|
- name: funda_listings
|
||||||
|
description: >
|
||||||
|
Analysis-ready Funda listings table. One row per listing, enriched with price history, derived
|
||||||
|
metrics like price per sqm, and all cleaned fields from staging.
|
||||||
|
meta:
|
||||||
|
dagster:
|
||||||
|
group: funda
|
||||||
|
columns:
|
||||||
|
- name: global_id
|
||||||
|
description: Funda internal listing ID.
|
||||||
|
tests:
|
||||||
|
- unique
|
||||||
|
- not_null
|
||||||
|
- name: current_price
|
||||||
|
description: Current asking or rental price in euros.
|
||||||
|
- name: price_per_sqm
|
||||||
|
description: Current price divided by living area in m².
|
||||||
|
- name: is_sold
|
||||||
|
description: True when a sold price event exists for this listing.
|
||||||
|
- name: sold_price
|
||||||
|
description: Final sold price, null if still available.
|
||||||
|
- name: sold_date
|
||||||
|
description: Date sold, null if still available.
|
||||||
|
|
||||||
|
- name: funda_city_stats
|
||||||
|
description: >
|
||||||
|
Aggregated price statistics per city, province, offering type and object type. Only includes
|
||||||
|
currently available (not sold) listings.
|
||||||
|
meta:
|
||||||
|
dagster:
|
||||||
|
group: funda
|
||||||
|
columns:
|
||||||
|
- name: city
|
||||||
|
description: City name.
|
||||||
|
tests:
|
||||||
|
- not_null
|
||||||
|
- name: listing_count
|
||||||
|
description: Number of active listings in this group.
|
||||||
|
- name: avg_price
|
||||||
|
description: Average asking price.
|
||||||
|
- name: median_price
|
||||||
|
description: Median asking price.
|
||||||
|
- name: avg_price_per_sqm
|
||||||
|
description: Average price per square metre.
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
version: 2
|
|
||||||
|
|
||||||
models:
|
|
||||||
- name: stg_funda_listings
|
|
||||||
description: >
|
|
||||||
Cleaned Funda listing details – one row per property.
|
|
||||||
meta:
|
|
||||||
dagster:
|
|
||||||
group: funda
|
|
||||||
columns:
|
|
||||||
- name: global_id
|
|
||||||
description: Funda internal listing ID.
|
|
||||||
tests:
|
|
||||||
- unique
|
|
||||||
- not_null
|
|
||||||
- name: city
|
|
||||||
description: City name.
|
|
||||||
- name: price
|
|
||||||
description: Asking or rental price in euros.
|
|
||||||
|
|
||||||
- name: stg_funda_price_history
|
|
||||||
description: >
|
|
||||||
Historical price events per listing (asking prices, WOZ assessments, sales).
|
|
||||||
meta:
|
|
||||||
dagster:
|
|
||||||
group: funda
|
|
||||||
columns:
|
|
||||||
- name: global_id
|
|
||||||
description: Funda internal listing ID.
|
|
||||||
tests:
|
|
||||||
- not_null
|
|
||||||
- name: price
|
|
||||||
description: Price at this point in time.
|
|
||||||
18
dbt/models/staging/stg_funda_listings.yml
Normal file
18
dbt/models/staging/stg_funda_listings.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
models:
|
||||||
|
- name: stg_funda_listings
|
||||||
|
description: Cleaned Funda listing details – one row per property.
|
||||||
|
meta:
|
||||||
|
dagster:
|
||||||
|
group: funda
|
||||||
|
columns:
|
||||||
|
- name: global_id
|
||||||
|
description: Funda internal listing ID.
|
||||||
|
tests:
|
||||||
|
- unique
|
||||||
|
- not_null
|
||||||
|
- name: city
|
||||||
|
description: City name.
|
||||||
|
- name: price
|
||||||
|
description: Asking or rental price in euros.
|
||||||
15
dbt/models/staging/stg_funda_price_history.yml
Normal file
15
dbt/models/staging/stg_funda_price_history.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
models:
|
||||||
|
- name: stg_funda_price_history
|
||||||
|
description: Historical price events per listing (asking prices, WOZ assessments, sales).
|
||||||
|
meta:
|
||||||
|
dagster:
|
||||||
|
group: funda
|
||||||
|
columns:
|
||||||
|
- name: global_id
|
||||||
|
description: Funda internal listing ID.
|
||||||
|
tests:
|
||||||
|
- not_null
|
||||||
|
- name: price
|
||||||
|
description: Price at this point in time.
|
||||||
Reference in New Issue
Block a user