|
/* |
|
DEP_EXT_sum_competitors |
|
Return a table with two additional columns: one for the selected retailer and one for the sum of competitors |
|
|
|
Example: A user has two datasets: a dataset of retailers and their industry (indicated competitors), |
|
and a geometry dataset with a JSON column of retailers. |
|
In the underlying source query (via a widget), |
|
a single retailer is selected from the simple retailer table dataset (ie. Dunkin Donuts). |
|
This function will return the geometry table with two additional columns of data pulled from the JSON column: |
|
one column of the total competing retailers in the same industry (ie. Starbucks, Peets, etc.) |
|
and one column of the number of Dunkin Donuts found in each count. |
|
|
|
If more than one retailer is selected, this function will only reflect the first retailer. |
|
|
|
|
|
Inputs managed by CARTO, common to all DEP_EXT functions: |
|
operation text: 'create' or 'populate' |
|
table_name text: the name of the previous node table |
|
primary_source_query text: the query on the previous node table |
|
primary_source_columns text: the columns of the previous node table |
|
User input: |
|
retailer_tablename text: the name of the table containing retailer and industry information |
|
industry_column text: the name of the column containing industry type in the retailer dataset |
|
json_table text: the name of the geometry dataset containing retailer information in JSON column |
|
json_column text: the name of the column containing the JSON objects |
|
key_field text: name of the column containing the key field in the underlying node (ie. 'company_name') |
|
dummy integer: input any integer and change in order to override cached table |
|
*/ |
|
|
|
CREATE OR REPLACE FUNCTION DEP_EXT_sum_competitors( |
|
operation text, |
|
table_name text, |
|
primary_source_query text, |
|
primary_source_columns text[], |
|
retailer_tablename text, |
|
industry_column text, |
|
json_table text, |
|
json_column text, |
|
key_field text, |
|
dummy integer |
|
) |
|
RETURNS VOID AS $$ |
|
DECLARE |
|
selected_retailer text; |
|
selected_columns text; |
|
selected_keys text[]; |
|
company text; |
|
query_string text; |
|
initial_query_string text; |
|
BEGIN |
|
|
|
-- grab all the columns from the json table |
|
EXECUTE 'SELECT array_to_string(ARRAY(' |
|
'SELECT column_name::text from INFORMATION_SCHEMA.COLUMNS ' |
|
'WHERE table_name = '''||json_table||'''),'','')' |
|
INTO selected_columns; |
|
|
|
-- grab the FIRST selected retailer... |
|
|
|
EXECUTE |
|
'WITH CTE as ('||primary_source_query|| |
|
') SELECT array_to_string(ARRAY(SELECT '||key_field|| |
|
' from CTE LIMIT 1), '','')' INTO selected_retailer; |
|
|
|
IF operation = 'create' THEN |
|
|
|
EXECUTE 'DROP TABLE IF EXISTS ' || table_name; |
|
|
|
-- the returned table will have the same schema as the geometry table plus ONE column |
|
EXECUTE |
|
'CREATE TABLE ' |
|
|| table_name |
|
|| ' AS SELECT ' || selected_columns |
|
|| ', null::numeric AS competitors' |
|
|| ', null::numeric AS selected_retailer' |
|
|| ' FROM (SELECT * FROM ' || json_table || ') _source' |
|
|| ' LIMIT 0'; |
|
|
|
ELSEIF operation = 'populate' THEN |
|
|
|
-- grab the keys (retailers) |
|
|
|
EXECUTE format( $QUERY$ |
|
WITH selected AS (%s), |
|
competitors AS ( |
|
SELECT * FROM %I |
|
WHERE %s in (SELECT %s FROM selected)) |
|
SELECT ARRAY(SELECT %s from competitors |
|
EXCEPT (SELECT %s from selected)) |
|
$QUERY$, |
|
primary_source_query, |
|
retailer_tablename, |
|
industry_column, |
|
industry_column, |
|
key_field, |
|
key_field) |
|
INTO selected_keys; |
|
|
|
|
|
-- build the table |
|
-- initialize first query_string |
|
query_string := '('||json_column||'::json->>$a$'||selected_retailer||'$a$)::numeric'; |
|
initial_query_string := query_string; |
|
-- for competitor in selected_keys: |
|
-- continue to build query string |
|
FOREACH company IN ARRAY selected_keys |
|
LOOP |
|
query_string := query_string || ' + (' || json_column || '::json->>$a$'||company||'$a$)::numeric'; |
|
END LOOP; |
|
EXECUTE format( $QUERY$ |
|
WITH result AS ( |
|
SELECT %s, (%s - %s)::numeric as competitors, %s as selected FROM %I |
|
) |
|
INSERT INTO %I SELECT * FROM result |
|
$QUERY$, |
|
selected_columns, |
|
query_string, |
|
initial_query_string, |
|
initial_query_string, |
|
json_table, |
|
table_name |
|
); |
|
|
|
END IF; |
|
END; |
|
$$ LANGUAGE plpgsql; |
|
|
|
|
|
-- tests ---------- |
|
|
|
-- try with two selections |
|
|
|
select * from DEP_EXT_sum_competitors( |
|
'create', |
|
'temptable_1', |
|
'select * from retailers_sheet1 where company in (''Dollar General'')', |
|
ARRAY['cartodb_id', 'the_geom', 'the_geom_webmercator', 'rank', 'company', '_2016_retail_sales_000', 'headquarters_u_s_headquarters', '_2016_stores', 'industry'], |
|
'retailers_sheet1', |
|
'industry', |
|
'county_company_counts', |
|
'company_count', |
|
'company', |
|
2 |
|
); |
|
|
|
select * from DEP_EXT_sum_competitors( |
|
'populate', |
|
'temptable_1', |
|
'select * from retailers_sheet1 where company in (''Target'')', |
|
ARRAY['cartodb_id', 'the_geom', 'the_geom_webmercator', 'rank', 'company', '_2016_retail_sales_000', 'headquarters_u_s_headquarters', '_2016_stores', 'industry'], |
|
'retailers_sheet1', |
|
'industry', |
|
'county_company_counts', |
|
'company_count', |
|
'company', |
|
2 |
|
); |