diff --git a/doc/measures_functions.md b/doc/measures_functions.md index a07ad93..be7e9f8 100644 --- a/doc/measures_functions.md +++ b/doc/measures_functions.md @@ -134,6 +134,40 @@ SET household_count = OBS_GetMeasure(the_geom, 'us.census.acs.B11001001') * If an unrecognized normalization type is input, raise an error: `'Only valid inputs for "normalize" are "area" (default) and "denominator".` +## OBS_GetMeasureById(geom_ref text, measure_id text, boundary_id text) + +The ```OBS_GetMeasureById(geom_ref, measure_id, boundary_id)``` function returns any Data Observatory measure that corresponds to the boundary in ```boundary_id``` that has a geometry reference of ```geom_ref```. + +#### Arguments + +Name |Description +--- | --- +geom_ref | a geometry reference (e.g., a US Census geoid) +measure_id | a measure identifier from the Data Observatory ([see available measures](https://cartodb.github.io/bigmetadata/observatory.pdf)) +boundary_id | source of geometries to pull measure from (e.g., 'us.census.tiger.census_tract') +time_span (optional) | time span of interest (e.g., 2010 - 2014). If `NULL` is passed, the measure from the most recent data will be used. + +#### Returns + +A NUMERIC value + +Key | Description +--- | --- +value | the raw measure associated with `geom_ref` + +#### Example + +Add a measure to an empty column based on county geoids in your table + +```SQL +UPDATE tablename +SET household_count = OBS_GetMeasureById(geoid_column, 'us.census.acs.B11001001', 'us.census.tiger.county') +``` + +#### Errors + +* Returns `NULL` if there is a mismatch between the geometry reference and the boundary id such as using the geoid of a county with the boundary of block groups + ## OBS_GetCategory(point geometry, category_id text) The ```OBS_GetCategory(point, category_id)``` function returns any Data Observatory Category value at a point location. The Categories available are currently limited to Segmentation categories. See the Segmentation section of the [Catalog](https://cartodb.github.io/bigmetadata/observatory.pdf) for more detail. diff --git a/src/pg/sql/41_observatory_augmentation.sql b/src/pg/sql/41_observatory_augmentation.sql index 6b64f60..544a18d 100644 --- a/src/pg/sql/41_observatory_augmentation.sql +++ b/src/pg/sql/41_observatory_augmentation.sql @@ -380,6 +380,53 @@ END; $$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetMeasureById( + geom_ref TEXT, + measure_id TEXT, + boundary_id TEXT, + time_span TEXT DEFAULT NULL +) +RETURNS NUMERIC +AS $$ +DECLARE + target_table TEXT; + colname TEXT; + measure_val NUMERIC; + data_geoid_colname TEXT; + test_query TEXT; +BEGIN + + SELECT x ->> 'colname', x ->> 'tablename' INTO colname, target_table + FROM cdb_observatory._OBS_GetColumnData(boundary_id, Array[measure_id], time_span) As x; + + EXECUTE + format('SELECT ct.colname + FROM observatory.obs_column_to_column c2c, + observatory.obs_column_table ct, + observatory.obs_table t + WHERE c2c.reltype = ''geom_ref'' + AND ct.column_id = c2c.source_id + AND ct.table_id = t.id + AND t.tablename = %L' + , target_table) + INTO data_geoid_colname; + + RAISE DEBUG 'target_table %, colname %', target_table, colname; + + EXECUTE format( + 'SELECT %I + FROM observatory.%I + WHERE %I.%I = %L', + colname, + target_table, + target_table, data_geoid_colname, geom_ref) + INTO measure_val; + + RETURN measure_val; + +END; +$$ LANGUAGE plpgsql; + CREATE OR REPLACE FUNCTION cdb_observatory.OBS_GetCategory( geom geometry(Geometry, 4326), category_id TEXT, diff --git a/src/pg/test/expected/41_observatory_augmentation_test.out b/src/pg/test/expected/41_observatory_augmentation_test.out index 0094351..8311660 100644 --- a/src/pg/test/expected/41_observatory_augmentation_test.out +++ b/src/pg/test/expected/41_observatory_augmentation_test.out @@ -76,3 +76,15 @@ t obs_getuscensuscategory_polygon t (1 row) +obs_getmeasurebyid_cartodb_census_tract +t +(1 row) +obs_getmeasurebyid_null_boundary_null_timespan +t +(1 row) +obs_getmeasurebyid_cartodb_block_group +t +(1 row) +obs_getmeasurebyid_nulls +t +(1 row) diff --git a/src/pg/test/sql/41_observatory_augmentation_test.sql b/src/pg/test/sql/41_observatory_augmentation_test.sql index 8061b18..8a3f023 100644 --- a/src/pg/test/sql/41_observatory_augmentation_test.sql +++ b/src/pg/test/sql/41_observatory_augmentation_test.sql @@ -204,4 +204,37 @@ SELECT cdb_observatory.OBS_GetUSCensusCategory( cdb_observatory._testarea(), 'Spielman-Singleton Segments: 10 Clusters') = 'Low income, mix of minorities' As OBS_GetUSCensusCategory_polygon; +-- OBS_GetMeasureById tests +-- typical query +SELECT (cdb_observatory.OBS_GetMeasureById( + '36047048500', + 'us.census.acs.B01003001', + 'us.census.tiger.census_tract', + '2010 - 2014' +) - 3241) / 3241 < 0.0001 As OBS_GetMeasureById_cartodb_census_tract; + +-- no boundary_id should give null +SELECT cdb_observatory.OBS_GetMeasureById( + '36047048500', + 'us.census.acs.B01003001', + NULL, + NULL +) IS NULL As OBS_GetMeasureById_null_boundary_null_timespan; + +-- query at block_group level +SELECT (cdb_observatory.OBS_GetMeasureById( + '360470485002', + 'us.census.acs.B01003001', + 'us.census.tiger.block_group', + '2010 - 2014' +) - 1900) / 1900 < 0.0001 As OBS_GetMeasureById_cartodb_block_group; + +-- geom ref / boundary mismatch +SELECT cdb_observatory.OBS_GetMeasureById( + '36047048500', + 'us.census.acs.B01003001', + 'us.census.tiger.block_group', + '2010 - 2014' +) IS NULL As OBS_GetMeasureById_nulls; + \i test/fixtures/drop_fixtures.sql