diff --git a/dbt/models/reporting/docs.md b/dbt/models/reporting/docs.md index bd094d35c..ab09c88fe 100644 --- a/dbt/models/reporting/docs.md +++ b/dbt/models/reporting/docs.md @@ -8,6 +8,20 @@ group, township, assessment stage, and year. Feeds public reporting assets. **Primary Key**: `year`, `stage_name`, `geo_id` {% enddocs %} +# ratio_curve + +{% docs table_ratio_curve %} +View for reporting model and desk review ratios by PIN and year. Feeds the desk +review ratio curve dashboard. + +### Assumptions + +- Pre-mailed values match what Res Val used to provide us with as desk review +values. + +**Primary Key**: `year`, `pin` +{% enddocs %} + # ratio_stats {% docs table_ratio_stats %} diff --git a/dbt/models/reporting/reporting.ratio_curve.sql b/dbt/models/reporting/reporting.ratio_curve.sql new file mode 100644 index 000000000..20fe1d611 --- /dev/null +++ b/dbt/models/reporting/reporting.ratio_curve.sql @@ -0,0 +1,72 @@ +-- Gathers model values, pre-mailed (desk review) values, and sale prices for +-- PINs that have both model and desk review values in the current year. Lets us +-- compare sales ratios for model values against desk review values to ensure +-- desk review is improving output. +{{ + config( + materialized='table' + ) +}} + +-- In order to compare desk review values against model values, we need final +-- model run IDs by township and year +WITH final_models AS ( + SELECT + final_model.run_id, + final_model.type, + towns.township_code + FROM {{ ref('model.final_model') }} AS final_model + CROSS JOIN + UNNEST(final_model.township_code_coverage) AS towns (township_code) +), + +-- Use the final model run IDs to grab the model values we need to compare Res +-- Val's desk review values against +model_vals AS ( + SELECT + assessment_pin.meta_pin AS pin, + assessment_pin.pred_pin_final_fmv_round AS model_value, + NULLIF(assessment_pin.sale_ratio_study_price, 0) AS sale_price, + assessment_pin.sale_ratio_study_date AS sale_date, + assessment_pin.sale_ratio_study_document_num AS sale_document_number, + assessment_pin.year, + assessment_pin.run_id, + final_models.type + FROM {{ source('model', 'assessment_pin') }} AS assessment_pin + INNER JOIN final_models + ON assessment_pin.run_id = final_models.run_id + AND assessment_pin.township_code = final_models.township_code +) + +-- We are not using the most_recent_pin CTE from the recurring data reqeuests +-- analysis since we can't really explain why res val provides PINs that only +-- appear in the prior year +SELECT + vpu.pin, + vpu.triad_name AS triad, + vpu.township_name AS township, + vpu.nbhd_code AS neighborhood, + vpu.year, + COALESCE(model_vals.sale_price IS NOT NULL, FALSE) + AS has_sale, + CAST(model_vals.sale_price AS BIGINT) AS sale_price, + model_vals.sale_date, + model_vals.sale_document_number, + -- These values are slightly different than the desk review values Res Val + -- provides due to rounding in iasWorld, but the differences are negligible + CAST(vpv.pre_mailed_tot * 10 AS BIGINT) AS desk_review_value, + vpv.pre_mailed_tot * 10 / model_vals.sale_price AS desk_review_ratio, + CAST(model_vals.model_value AS BIGINT) AS model_value, + model_vals.model_value / model_vals.sale_price AS model_ratio, + model_vals.run_id AS model_run_id, + model_vals.type AS model_type +FROM {{ ref('default.vw_pin_universe') }} AS vpu +-- Inner joins to only pull PINs that have both model and desk review values +-- This should also ensure that we are only pulling regression class parcels +INNER JOIN model_vals + ON vpu.pin = model_vals.pin + AND vpu.year = model_vals.year +INNER JOIN {{ ref('default.vw_pin_value') }} AS vpv + ON vpu.pin = vpv.pin + AND vpu.year = vpv.year + AND vpv.pre_mailed_tot IS NOT NULL