2026-03-26 08:37:53 +00:00
|
|
|
-- Mart: Canonical school dimension — one row per active URN
|
|
|
|
|
|
2026-07-01 21:53:11 +01:00
|
|
|
-- int_ofsted_latest is only ref()'d inside a conditional block below (it may not
|
|
|
|
|
-- exist before the Ofsted pipeline first runs), so declare the dependency
|
|
|
|
|
-- explicitly for dbt's DAG.
|
|
|
|
|
-- depends_on: {{ ref('int_ofsted_latest') }}
|
|
|
|
|
|
2026-03-26 08:37:53 +00:00
|
|
|
with schools as (
|
|
|
|
|
select * from {{ ref('stg_gias_establishments') }}
|
|
|
|
|
)
|
|
|
|
|
|
2026-03-26 20:43:24 +00:00
|
|
|
{% set ofsted_relation = adapter.get_relation(
|
|
|
|
|
database=target.database,
|
2026-04-13 14:51:14 +01:00
|
|
|
schema='intermediate',
|
2026-03-26 20:43:24 +00:00
|
|
|
identifier='int_ofsted_latest'
|
|
|
|
|
) %}
|
|
|
|
|
|
2026-03-26 08:37:53 +00:00
|
|
|
select
|
|
|
|
|
s.urn,
|
|
|
|
|
s.local_authority_code * 1000 + s.establishment_number as laestab,
|
|
|
|
|
s.school_name,
|
2026-07-09 10:45:15 +01:00
|
|
|
-- Phase in GIAS code space (see seeds/gias_code_names.csv):
|
|
|
|
|
-- 2 = Primary, 4 = Secondary, 7 = All-through, 0 = Not applicable.
|
2026-04-01 16:18:52 +01:00
|
|
|
case
|
2026-07-09 10:45:15 +01:00
|
|
|
-- 1. Trust GIAS phase when it's a real value (0 = the catch-all "Not Applicable")
|
|
|
|
|
when s.phase_code is not null and s.phase_code != 0
|
|
|
|
|
then s.phase_code
|
2026-04-07 21:15:54 +01:00
|
|
|
-- 2. Infer from statutory age range (independent schools still publish these)
|
2026-07-09 10:45:15 +01:00
|
|
|
when s.statutory_high_age is not null and s.statutory_high_age <= 11 then 2
|
|
|
|
|
when s.statutory_low_age is not null and s.statutory_low_age >= 11 then 4
|
2026-04-01 16:18:52 +01:00
|
|
|
when s.statutory_low_age is not null and s.statutory_high_age is not null
|
2026-07-09 10:45:15 +01:00
|
|
|
and s.statutory_low_age < 11 and s.statutory_high_age > 11 then 7
|
2026-04-07 21:15:54 +01:00
|
|
|
-- 3. Fallback: infer from school name (covers independents with missing ages)
|
|
|
|
|
when s.school_name ilike '%primary%'
|
|
|
|
|
or s.school_name ilike '%infant%'
|
|
|
|
|
or s.school_name ilike '%junior%'
|
|
|
|
|
or s.school_name ilike '%preparatory%'
|
|
|
|
|
or s.school_name ilike '% prep school%'
|
|
|
|
|
or s.school_name ilike '% prep %'
|
2026-07-09 10:45:15 +01:00
|
|
|
then 2
|
2026-04-07 21:15:54 +01:00
|
|
|
when s.school_name ilike '%secondary%'
|
|
|
|
|
or s.school_name ilike '%high school%'
|
|
|
|
|
or s.school_name ilike '%grammar%'
|
|
|
|
|
or s.school_name ilike '%senior school%'
|
|
|
|
|
or s.school_name ilike '%upper school%'
|
2026-07-09 10:45:15 +01:00
|
|
|
then 4
|
|
|
|
|
-- 4. Give up — null renders no phase pill
|
2026-04-07 21:15:54 +01:00
|
|
|
else null
|
2026-07-09 10:45:15 +01:00
|
|
|
end as phase_code,
|
|
|
|
|
s.school_type_code,
|
2026-03-26 08:37:53 +00:00
|
|
|
s.academy_trust_name,
|
|
|
|
|
s.academy_trust_uid,
|
2026-07-09 10:45:15 +01:00
|
|
|
s.religious_character_code,
|
2026-03-26 08:37:53 +00:00
|
|
|
s.gender,
|
|
|
|
|
s.statutory_low_age || '-' || s.statutory_high_age as age_range,
|
2026-07-09 10:45:15 +01:00
|
|
|
-- GIAS OfficialSixthForm in code space: 1 = has, 2 = does not, 0 = N/A.
|
|
|
|
|
-- Null (rare, new establishments) falls back to the statutory age range.
|
2026-07-07 10:30:39 +01:00
|
|
|
case
|
2026-07-09 10:45:15 +01:00
|
|
|
when s.official_sixth_form_code = 1 then true
|
|
|
|
|
when s.official_sixth_form_code in (0, 2) then false
|
2026-07-07 10:30:39 +01:00
|
|
|
else coalesce(s.statutory_high_age >= 18, false)
|
|
|
|
|
end as has_sixth_form,
|
2026-03-26 08:37:53 +00:00
|
|
|
s.capacity,
|
|
|
|
|
s.total_pupils,
|
|
|
|
|
concat_ws(' ', s.head_title, s.head_first_name, s.head_last_name) as headteacher_name,
|
|
|
|
|
s.website,
|
|
|
|
|
s.telephone,
|
|
|
|
|
s.open_date,
|
|
|
|
|
s.close_date,
|
2026-07-09 10:45:15 +01:00
|
|
|
s.status_code,
|
2026-03-26 08:37:53 +00:00
|
|
|
s.nursery_provision,
|
2026-07-09 10:45:15 +01:00
|
|
|
s.admissions_policy_code,
|
2026-03-26 08:37:53 +00:00
|
|
|
|
2026-03-26 20:43:24 +00:00
|
|
|
-- Latest Ofsted (populated after monthly Ofsted pipeline runs)
|
|
|
|
|
{% if ofsted_relation is not none %}
|
2026-07-01 21:44:01 +01:00
|
|
|
-- Prefer the graded overall effectiveness; fall back to the grade parsed
|
|
|
|
|
-- from the latest ungraded (Section 8) outcome when no graded grade exists.
|
|
|
|
|
coalesce(o.overall_effectiveness, o.ungraded_grade) as ofsted_grade,
|
2026-03-26 08:37:53 +00:00
|
|
|
o.inspection_date as ofsted_date,
|
|
|
|
|
o.framework as ofsted_framework
|
2026-03-26 20:43:24 +00:00
|
|
|
{% else %}
|
|
|
|
|
null::text as ofsted_grade,
|
|
|
|
|
null::date as ofsted_date,
|
|
|
|
|
null::text as ofsted_framework
|
|
|
|
|
{% endif %}
|
2026-03-26 08:37:53 +00:00
|
|
|
|
|
|
|
|
from schools s
|
2026-03-26 20:43:24 +00:00
|
|
|
{% if ofsted_relation is not none %}
|
|
|
|
|
left join {{ ref('int_ofsted_latest') }} o on s.urn = o.urn
|
|
|
|
|
{% endif %}
|
2026-07-09 10:45:15 +01:00
|
|
|
-- 1 = Open; 3 = Open, but proposed to close (still operating; drops out when
|
|
|
|
|
-- GIAS flips to Closed — marts fully rebuild each run).
|
|
|
|
|
where s.status_code in (1, 3)
|