|
1 | | --- Similar logic to zoning districts: |
2 | | --- calculate how much (total area and percentage) of each lot is covered by MIH areas |
3 | | --- assign the MIH project ID to each tax lot based on which MIH area covers the |
4 | | --- majority of the lot |
5 | | --- a MIH area is only assigned if more than 10% of the lot is covered by the MIH area |
6 | | --- OR more than 50% of the MIH area overlaps with the lot |
7 | | -DROP TABLE IF EXISTS mihperorder; |
8 | | -CREATE TABLE mihperorder AS |
9 | | -WITH mih_unioned AS ( |
10 | | - SELECT |
11 | | - project_name, |
12 | | - mih_option AS affordability_option, |
13 | | - ST_UNION(wkb_geometry) AS wkb_geometry |
14 | | - FROM dcp_mih |
15 | | - GROUP BY project_name, mih_option |
16 | | -), |
17 | | -mihper AS ( |
| 1 | +DROP TABLE IF EXISTS mih_cleaned; |
| 2 | +CREATE TABLE mih_cleaned AS |
| 3 | +SELECT |
| 4 | + project_id || '-' || mih_option AS mih_id, |
| 5 | + *, |
| 6 | + trim( |
| 7 | + -- Step 2b: collapse any sequence of commas (e.g., ",,", ",,,") |
| 8 | + regexp_replace( |
| 9 | + -- Step 2a: Replace "and" or "," (with any spaces) with a single comma |
| 10 | + regexp_replace( |
| 11 | + -- Step 1: Add space between "Option" and number |
| 12 | + regexp_replace( |
| 13 | + replace(mih_option, 'Affordablility', 'Affordability'), -- should probably fix this in the source data |
| 14 | + 'Option(\d)', -- ← match "Option" followed by a digit |
| 15 | + 'Option \1', -- ← insert space |
| 16 | + 'g' |
| 17 | + ), |
| 18 | + '\s*(,|and)\s*', -- ← match a comma or "and" (with spaces) |
| 19 | + ',', -- ← replace with a comma |
| 20 | + 'g' |
| 21 | + ), |
| 22 | + ',+', -- ← match one or more commas in a row |
| 23 | + ',', -- ← replace with a single comma |
| 24 | + 'g' |
| 25 | + ), |
| 26 | + ', ' -- ← trim comma and space FROM start/end |
| 27 | + ) AS cleaned_option |
| 28 | +FROM dcp_mih; |
| 29 | + |
| 30 | + |
| 31 | +DROP TABLE IF EXISTS mih_lot_overlap CASCADE; |
| 32 | +CREATE TABLE mih_lot_overlap AS |
| 33 | +WITH mih_per_area AS ( |
18 | 34 | SELECT |
19 | | - p.id, |
20 | 35 | p.bbl, |
21 | | - m.project_name, |
22 | | - m.affordability_option, |
23 | | - ST_AREA( |
| 36 | + m.project_id, |
| 37 | + m.mih_id, |
| 38 | + m.wkb_geometry AS mih_geom, |
| 39 | + p.geom AS lot_geom, |
| 40 | + m.cleaned_option, |
| 41 | + st_area( |
24 | 42 | CASE |
25 | | - WHEN ST_COVEREDBY(p.geom, m.wkb_geometry) THEN p.geom |
26 | | - ELSE ST_MULTI(ST_INTERSECTION(p.geom, m.wkb_geometry)) |
| 43 | + WHEN st_coveredby(p.geom, m.wkb_geometry) THEN p.geom |
| 44 | + ELSE st_multi(st_intersection(p.geom, m.wkb_geometry)) |
27 | 45 | END |
28 | 46 | ) AS segbblgeom, |
29 | | - ST_AREA(p.geom) AS allbblgeom, |
30 | | - ST_AREA( |
| 47 | + st_area(p.geom) AS allbblgeom, |
| 48 | + st_area( |
31 | 49 | CASE |
32 | | - WHEN ST_COVEREDBY(m.wkb_geometry, p.geom) THEN m.wkb_geometry |
33 | | - ELSE ST_MULTI(ST_INTERSECTION(m.wkb_geometry, p.geom)) |
| 50 | + WHEN st_coveredby(m.wkb_geometry, p.geom) THEN m.wkb_geometry |
| 51 | + ELSE st_multi(st_intersection(m.wkb_geometry, p.geom)) |
34 | 52 | END |
35 | 53 | ) AS segmihgeom, |
36 | | - ST_AREA(m.wkb_geometry) AS allmihgeom |
| 54 | + st_area(m.wkb_geometry) AS allmihgeom |
37 | 55 | FROM pluto AS p |
38 | | - INNER JOIN mih_unioned AS m |
39 | | - ON ST_INTERSECTS(p.geom, m.wkb_geometry) |
| 56 | + INNER JOIN mih_cleaned AS m |
| 57 | + ON st_intersects(p.geom, m.wkb_geometry) |
40 | 58 | ), |
41 | | -grouped AS ( |
| 59 | +mih_areas AS ( |
42 | 60 | SELECT |
43 | | - id, |
44 | 61 | bbl, |
45 | | - project_name, |
46 | | - affordability_option, |
47 | | - SUM(segbblgeom) AS segbblgeom, |
48 | | - SUM(segmihgeom) AS segmihgeom, |
49 | | - SUM(segbblgeom / allbblgeom) * 100 AS perbblgeom, |
50 | | - MAX(segmihgeom / allmihgeom) * 100 AS maxpermihgeom |
51 | | - FROM mihper |
52 | | - GROUP BY id, bbl, project_name, affordability_option |
| 62 | + cleaned_option, |
| 63 | + project_id, |
| 64 | + mih_id, |
| 65 | + sum(segbblgeom) AS segbblgeom, |
| 66 | + sum(segmihgeom) AS segmihgeom, |
| 67 | + sum(segbblgeom / allbblgeom) * 100 AS perbblgeom, |
| 68 | + max(segmihgeom / allmihgeom) * 100 AS maxpermihgeom |
| 69 | + FROM mih_per_area |
| 70 | + GROUP BY bbl, cleaned_option, project_id, mih_id |
53 | 71 | ) |
54 | | -SELECT |
55 | | - id, |
56 | | - bbl, |
57 | | - project_name, |
58 | | - affordability_option, |
59 | | - segbblgeom, |
60 | | - perbblgeom, |
61 | | - maxpermihgeom, |
62 | | - ROW_NUMBER() OVER ( |
63 | | - PARTITION BY id |
64 | | - ORDER BY segbblgeom DESC, segmihgeom DESC |
65 | | - ) AS row_number |
66 | | -FROM grouped |
| 72 | +SELECT * FROM mih_areas |
67 | 73 | WHERE perbblgeom >= 10 OR maxpermihgeom >= 50; |
68 | 74 |
|
69 | | --- assign the MIH project name and affordability option with the highest overlap to each lot |
70 | | -UPDATE pluto a |
| 75 | + |
| 76 | +-- NOTE: GIS will likely refactor dcp_mih into this pivoted format, |
| 77 | +-- so much this code will likely disappear. |
| 78 | +-- |
| 79 | +-- Find all distinct MIH areas that apply to a lot, and pivot to columns. |
| 80 | +-- e.g. if we have two rows from our geospatial join like so: |
| 81 | +-- bbl=123, mih_options=Option 1,Option 2 |
| 82 | +-- bbl=123, mih_options=Option 2,Option 3 |
| 83 | +-- we first aggregate to |
| 84 | +-- bbl=123, Option 1,Option 2,Option 2,Option 3 |
| 85 | +-- then pivot into distinct columns |
| 86 | +WITH bbls_with_all_options AS ( |
| 87 | + SELECT |
| 88 | + bbl, |
| 89 | + string_agg(cleaned_option, ',') AS all_options |
| 90 | + FROM mih_lot_overlap |
| 91 | + GROUP BY bbl |
| 92 | +), pivoted AS ( |
| 93 | + SELECT |
| 94 | + bbl, |
| 95 | + CASE |
| 96 | + WHEN (all_options LIKE '%Option 1%') = true THEN '1' |
| 97 | + END AS mih_opt1, |
| 98 | + CASE |
| 99 | + WHEN (all_options LIKE '%Option 2%') = true THEN '1' |
| 100 | + END AS mih_opt2, |
| 101 | + CASE |
| 102 | + WHEN (all_options LIKE '%Option 3%' OR all_options LIKE '%Deep Affordability Option%') = true THEN '1' |
| 103 | + END AS mih_opt3, |
| 104 | + CASE |
| 105 | + WHEN (all_options LIKE '%Deep Affordability Option%') = true THEN '1' |
| 106 | + END AS mih_opt4 |
| 107 | + FROM bbls_with_all_options |
| 108 | +) |
| 109 | +UPDATE pluto |
71 | 110 | SET |
72 | | - mih_project_name = b.project_name, |
73 | | - mih_affordability_option = b.affordability_option |
74 | | -FROM mihperorder AS b |
75 | | -WHERE |
76 | | - a.id = b.id |
77 | | - AND row_number = 1; |
| 111 | + mih_opt1 = m.mih_opt1, |
| 112 | + mih_opt2 = m.mih_opt2, |
| 113 | + mih_opt3 = m.mih_opt3, |
| 114 | + mih_opt4 = m.mih_opt4 |
| 115 | +FROM pivoted AS m |
| 116 | +WHERE pluto.bbl = m.bbl |
0 commit comments