Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NWM 3.0 fixes #498

Merged
merged 13 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Core/EC2/RDSBastion/scripts/viz/postgresql_setup.sh.tftpl
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ VIZ_PROC_DEV_RW_USER="${VIZ_PROC_DEV_RW_USER}"
VIZ_PROC_DEV_RW_PASS="${VIZ_PROC_DEV_RW_PASS}"

### set correct db dump file names / versions here - These should be in the S3 bucket at {DEPLOYMENT_BUCKET}/viz/db_pipeline/db_dumps ###
egisDB_services="egisDB_services_2023_0214.dump"
egisDB_services="egisDB_services_2023_0725.dump"
egisDB_reference="egisDB_reference_2023_0613.dump"
egisDB_aep_fim="egisDB_aep_fim_2023_0613.dump"
egisDB_fim_catchments="egisDB_fim_catchments_2023_0613.dump"

vizDB_admin="vizDB_admin_2023_0424.dump"
vizDB_archive="vizDB_archive_2023_0214.dump"
vizDB_cache="vizDB_cache_2023_0424.dump"
vizDB_cache="vizDB_cache_2023_0725.dump"
vizDB_derived="vizDB_derived_2023_0613.dump"
vizDB_ingest="vizDB_ingest_2023_0503.dump"
vizDB_publish="vizDB_publish_2023_0224.dump"
vizDB_ingest="vizDB_ingest_2023_0725.dump"
vizDB_publish="vizDB_publish_2023_0725.dump"
vizDB_external="vizDB_external_2023_0214.dump"

### install postgresql ###
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def lambda_handler(event, context):

# Admin tasks
if folder == 'admin':
run_admin_tasks(event, folder, step, sql_replace)
run_admin_tasks(event, folder, step, sql_replace, reference_time)
else:
# Max Flow
if step == "max_flows":
Expand Down Expand Up @@ -48,11 +48,12 @@ def lambda_handler(event, context):
return True

# Special function to handle admin-only sql tasks
def run_admin_tasks(event, folder, step, sql_replace):
def run_admin_tasks(event, folder, step, sql_replace, reference_time):
past_event = True if len(sql_replace) > 1 else False
target_table = event['args']['db_ingest_group']['target_table']
index_columns = event['args']['db_ingest_group']['index_columns']
index_name = event['args']['db_ingest_group']['index_name']
dependent_on = event['args']['db_ingest_group']['dependent_on']
target_schema = target_table.split('.')[0]
target_table_only = target_table.split('.')[-1]

Expand All @@ -61,7 +62,11 @@ def run_admin_tasks(event, folder, step, sql_replace):
sql_replace.update({"{target_schema}": target_schema})
sql_replace.update({"{index_name}": index_name})
sql_replace.update({"{index_columns}": index_columns})


# This will effectively pause an ingest group / pipeline if a dependent_on key is present - currently used to have MRF NBM run after MRF GFS
if dependent_on != "":
database(db_type="viz").check_required_tables_updated(f"SELECT * FROM {dependent_on} LIMIT 1", sql_replace, reference_time, raise_if_false=True)

if step == 'ingest_prep':
# if target table is not the original table, run the create command to create the table
if past_event is True:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ SELECT forecasts.feature_id,
round((max(CASE WHEN forecasts.forecast_hour <= 120 THEN forecasts.streamflow ELSE NULL END) * 35.315)::numeric, 2) AS maxflow_5day_cfs,
round((max(forecasts.streamflow) * 35.315)::numeric, 2) AS maxflow_10day_cfs
INTO cache.mrf_gfs_max_flows_alaska
FROM ingest.nwm_channel_rt_mrf_gfs_alaska forecasts
FROM ingest.nwm_channel_rt_mrf_gfs_alaska_mem1 forecasts
GROUP BY forecasts.feature_id, forecasts.reference_time, forecasts.nwm_vers;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
DROP TABLE IF EXISTS publish.mrf_gfs_10day_peak_flow_arrival_time_alaska;

WITH arrival_time AS(
SELECT
forecasts.feature_id,
max(forecasts.forecast_hour)+1 AS t_normal
FROM ingest.nwm_channel_rt_mrf_gfs_alaska_mem1 AS forecasts
GROUP BY forecasts.feature_id
)

SELECT
forecasts.feature_id,
forecasts.feature_id::TEXT AS feature_id_str,
min(forecasts.forecast_hour) AS peak_flow_arrival_hour,
forecasts.nwm_vers,
forecasts.reference_time,
max_flows.maxflow_10day_cfs AS max_flow_cfs,
arrival_time.t_normal AS below_bank_return_time,
to_char(now()::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS update_time,
channels.strm_order::integer,
channels.name,
channels.huc6,
'AK' as state,
-9999.0 as high_water_threshold,
channels.geom

INTO publish.mrf_gfs_10day_peak_flow_arrival_time_alaska
FROM ingest.nwm_channel_rt_mrf_gfs_alaska_mem1 AS forecasts

-- Join in max flows on max streamflow to only get peak flows
JOIN cache.mrf_gfs_max_flows_alaska AS max_flows
ON forecasts.feature_id = max_flows.feature_id AND round((forecasts.streamflow*35.315)::numeric, 2) = max_flows.maxflow_10day_cfs

-- Join in channels data to get reach metadata and geometry
JOIN derived.channels_alaska as channels ON forecasts.feature_id = channels.feature_id::bigint

-- Join in arrival_time
JOIN arrival_time ON forecasts.feature_id = arrival_time.feature_id

GROUP BY forecasts.feature_id, forecasts.reference_time, forecasts.nwm_vers, forecasts.streamflow, max_flows.maxflow_10day_cfs, arrival_time.t_normal, channels.geom, channels.strm_order, channels.name, channels.huc6;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
DROP TABLE IF EXISTS publish.mrf_nbm_10day_peak_flow_arrival_time_alaska;

WITH arrival_time AS(
SELECT
forecasts.feature_id,
max(forecasts.forecast_hour)+1 AS t_normal
FROM ingest.nwm_channel_rt_mrf_nbm_alaska AS forecasts
GROUP BY forecasts.feature_id
)

SELECT
forecasts.feature_id,
forecasts.feature_id::TEXT AS feature_id_str,
min(forecasts.forecast_hour) AS peak_flow_arrival_hour,
forecasts.nwm_vers,
forecasts.reference_time,
max_flows.maxflow_10day_cfs AS max_flow_cfs,
arrival_time.t_normal AS below_bank_return_time,
to_char(now()::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS update_time,
channels.strm_order::integer,
channels.name,
channels.huc6,
'AK' as state,
-9999.0 as high_water_threshold,
channels.geom

INTO publish.mrf_nbm_10day_peak_flow_arrival_time_alaska
FROM ingest.nwm_channel_rt_mrf_nbm_alaska AS forecasts

-- Join in max flows on max streamflow to only get peak flows
JOIN cache.mrf_nbm_max_flows_alaska AS max_flows
ON forecasts.feature_id = max_flows.feature_id AND round((forecasts.streamflow*35.315)::numeric, 2) = max_flows.maxflow_10day_cfs

-- Join in channels data to get reach metadata and geometry
JOIN derived.channels_alaska as channels ON forecasts.feature_id = channels.feature_id::bigint

-- Join in arrival_time
JOIN arrival_time ON forecasts.feature_id = arrival_time.feature_id

GROUP BY forecasts.feature_id, forecasts.reference_time, forecasts.nwm_vers, forecasts.streamflow, max_flows.maxflow_10day_cfs, arrival_time.t_normal, channels.geom, channels.strm_order, channels.name, channels.huc6;
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
DROP TABLE IF EXISTS publish.srf_peak_flow_arrival_time_alaska;
DROP TABLE IF EXISTS publish.srf_15hr_peak_flow_arrival_time_alaska;

WITH arrival_time AS (
SELECT
Expand All @@ -20,8 +20,9 @@ SELECT
channels.name,
channels.huc6,
'AK' AS state,
-9999.0 as high_water_threshold,
channels.geom
INTO publish.srf_peak_flow_arrival_time_alaska
INTO publish.srf_15hr_peak_flow_arrival_time_alaska
FROM ingest.nwm_channel_rt_srf_alaska AS forecasts

-- Join in max flows on max streamflow to only get peak flows
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
--------------- Building Footprints ---------------
DROP TABLE IF EXISTS publish.mrf_nbm_max_inundation_10day_building_footprints;
SELECT
buildings.build_id,
buildings.occ_cls,
buildings.prim_occ,
buildings.prop_st,
buildings.sqfeet,
buildings.height,
buildings.censuscode,
buildings.prod_date,
buildings.source,
buildings.val_method,
fim.hydro_id,
fim.hydro_id_str::TEXT AS hydro_id_str,
fim.feature_id,
fim.feature_id_str::TEXT AS feature_id_str,
fim.streamflow_cfs,
fim.hand_stage_ft,
buildings.geom,
ST_Centroid(buildings.geom) as geom_xy
INTO publish.mrf_nbm_max_inundation_10day_building_footprints
FROM external.building_footprints_fema as buildings
JOIN publish.mrf_nbm_max_inundation_10day fim ON ST_INTERSECTS(fim.geom, buildings.geom);

--------------- County Summary ---------------
DROP TABLE IF EXISTS publish.mrf_nbm_max_inundation_10day_counties;
SELECT
counties.geoid,
counties.name as county,
buildings.prop_st as state,
max(fim.streamflow_cfs) AS max_flow_cfs,
avg(fim.streamflow_cfs) AS avg_flow_cfs,
max(fim.hand_stage_ft) AS max_hand_stage_ft,
avg(fim.hand_stage_ft) AS avg_hand_stage_ft,
count(buildings.build_id) AS buildings_impacted,
sum(buildings.sqfeet) AS building_sqft_impacted,
sum(CASE WHEN buildings.occ_cls = 'Agriculture' THEN 1 ELSE 0 END) AS bldgs_agriculture,
sum(CASE WHEN buildings.occ_cls = 'Assembly' THEN 1 ELSE 0 END) AS bldgs_assembly,
sum(CASE WHEN buildings.occ_cls = 'Commercial' THEN 1 ELSE 0 END) AS bldgs_commercial,
sum(CASE WHEN buildings.occ_cls = 'Education' THEN 1 ELSE 0 END) AS bldgs_education,
sum(CASE WHEN buildings.occ_cls = 'Government' THEN 1 ELSE 0 END) AS bldgs_government,
sum(CASE WHEN buildings.occ_cls = 'Industrial' THEN 1 ELSE 0 END) AS bldgs_industrial,
sum(CASE WHEN buildings.occ_cls = 'Residential' THEN 1 ELSE 0 END) AS bldgs_residential,
sum(CASE WHEN buildings.occ_cls = 'Utility and Misc' THEN 1 ELSE 0 END) AS bldgs_utility_msc,
sum(CASE WHEN buildings.occ_cls = 'Other' THEN 1 WHEN buildings.occ_cls = 'Unclassified' THEN 1 WHEN buildings.occ_cls IS NULL THEN 1 ELSE 0 END) AS bldgs_other,
to_char('1900-01-01 00:00:00'::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS reference_time,
to_char(now()::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS update_time,
counties.geom
INTO publish.mrf_nbm_max_inundation_10day_counties
FROM derived.counties AS counties
JOIN derived.channels_county_crosswalk AS crosswalk ON counties.geoid = crosswalk.geoid
JOIN publish.mrf_nbm_max_inundation_10day AS fim on crosswalk.feature_id = fim.feature_id
JOIN publish.mrf_nbm_max_inundation_10day_building_footprints AS buildings ON crosswalk.feature_id = buildings.feature_id
GROUP BY counties.geoid, counties.name, counties.geom, buildings.prop_st;

-------------- HUCS Summary ---------------
DROP TABLE IF EXISTS publish.mrf_nbm_max_inundation_10day_hucs;
SELECT
hucs.huc8,
TO_CHAR(hucs.huc8, 'fm0000000000') AS huc8_str,
max(fim.streamflow_cfs) AS max_flow_cfs,
avg(fim.streamflow_cfs) AS avg_flow_cfs,
max(fim.hand_stage_ft) AS max_hand_stage_ft,
avg(fim.hand_stage_ft) AS avg_hand_stage_ft,
count(buildings.build_id) AS buildings_impacted,
sum(buildings.sqfeet) AS building_sqft_impacted,
sum(CASE WHEN buildings.occ_cls = 'Agriculture' THEN 1 ELSE 0 END) AS bldgs_agriculture,
sum(CASE WHEN buildings.occ_cls = 'Assembly' THEN 1 ELSE 0 END) AS bldgs_assembly,
sum(CASE WHEN buildings.occ_cls = 'Commercial' THEN 1 ELSE 0 END) AS bldgs_commercial,
sum(CASE WHEN buildings.occ_cls = 'Education' THEN 1 ELSE 0 END) AS bldgs_education,
sum(CASE WHEN buildings.occ_cls = 'Government' THEN 1 ELSE 0 END) AS bldgs_government,
sum(CASE WHEN buildings.occ_cls = 'Industrial' THEN 1 ELSE 0 END) AS bldgs_industrial,
sum(CASE WHEN buildings.occ_cls = 'Residential' THEN 1 ELSE 0 END) AS bldgs_residential,
sum(CASE WHEN buildings.occ_cls = 'Utility and Misc' THEN 1 ELSE 0 END) AS bldgs_utility_msc,
sum(CASE WHEN buildings.occ_cls = 'Other' THEN 1 WHEN buildings.occ_cls = 'Unclassified' THEN 1 WHEN buildings.occ_cls IS NULL THEN 1 ELSE 0 END) AS bldgs_other,
to_char('1900-01-01 00:00:00'::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS reference_time,
to_char(now()::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS update_time,
hucs.geom
INTO publish.mrf_nbm_max_inundation_10day_hucs
FROM derived.huc8s_conus AS hucs
JOIN derived.featureid_huc_crosswalk AS crosswalk ON hucs.huc8 = crosswalk.huc8
JOIN publish.mrf_nbm_max_inundation_10day AS fim on crosswalk.feature_id = fim.feature_id
JOIN publish.mrf_nbm_max_inundation_10day_building_footprints AS buildings ON crosswalk.feature_id = buildings.feature_id
GROUP BY hucs.huc8, hucs.geom;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- Synthetic Rating Curve Skill layers
DROP TABLE IF EXISTS publish.mrf_nbm_max_inundation_10day_src_skill;

SELECT
LPAD(urc.location_id::text, 8, '0') as usgs_site_code,
ht.feature_id,
ht.feature_id::text as feature_id_str,
to_char('1900-01-01 00:00:00'::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS reference_time,
maxflow_10day_cfs,
MIN(ht.elevation_ft) + ((maxflow_10day_cfs - MIN(ht.discharge_cfs)) * ((MAX(ht.next_elevation_ft) - MIN(ht.elevation_ft)) / (MAX(ht.next_discharge_cfs) - MIN(ht.discharge_cfs)))) as synth_interp_elevation_ft,
MIN(urc.elevation_ft) + ((maxflow_10day_cfs - MIN(urc.discharge_cfs)) * ((MAX(urc.next_elevation_ft) - MIN(urc.elevation_ft)) / (MAX(urc.next_discharge_cfs) - MIN(urc.discharge_cfs)))) as usgs_interp_elevation_ft,
MIN(ht.elevation_ft) + ((maxflow_10day_cfs - MIN(ht.discharge_cfs)) * ((MAX(ht.next_elevation_ft) - MIN(ht.elevation_ft)) / (MAX(ht.next_discharge_cfs) - MIN(ht.discharge_cfs)))) -
MIN(urc.elevation_ft) + ((maxflow_10day_cfs - MIN(urc.discharge_cfs)) * ((MAX(urc.next_elevation_ft) - MIN(urc.elevation_ft)) / (MAX(urc.next_discharge_cfs) - MIN(urc.discharge_cfs)))) as diff_ft,
MIN(navd88_datum) as navd88_datum,
MIN(stage) as usgs_stage,
ST_TRANSFORM(MIN(gage.geo_point), 3857) as geom
INTO publish.mrf_nbm_max_inundation_10day_src_skill
FROM cache.max_flows_mrf_nbm AS mrf
JOIN derived.recurrence_flows_conus thresholds ON mrf.feature_id = thresholds.feature_id AND mrf.maxflow_10day_cfs >= thresholds.high_water_threshold
JOIN derived.hydrotable_staggered AS ht ON ht.feature_id = mrf.feature_id AND mrf.maxflow_10day_cfs >= ht.discharge_cfs AND mrf.maxflow_10day_cfs <= ht.next_discharge_cfs
JOIN derived.usgs_rating_curves_staggered AS urc ON urc.location_id::text = ht.location_id AND mrf.maxflow_10day_cfs >= urc.discharge_cfs AND mrf.maxflow_10day_cfs <= urc.next_discharge_cfs
JOIN external.usgs_gage AS gage ON LPAD(gage.usgs_gage_id::text, 8, '0') = LPAD(ht.location_id::text, 8, '0')
GROUP BY urc.location_id, ht.feature_id, maxflow_10day_cfs;
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
--------------- Building Footprints ---------------
DROP TABLE IF EXISTS publish.mrf_nbm_max_inundation_3day_building_footprints;
SELECT
buildings.build_id,
buildings.occ_cls,
buildings.prim_occ,
buildings.prop_st,
buildings.sqfeet,
buildings.height,
buildings.censuscode,
buildings.prod_date,
buildings.source,
buildings.val_method,
fim.hydro_id,
fim.hydro_id_str::TEXT AS hydro_id_str,
fim.feature_id,
fim.feature_id_str::TEXT AS feature_id_str,
fim.streamflow_cfs,
fim.hand_stage_ft,
buildings.geom,
ST_Centroid(buildings.geom) as geom_xy
INTO publish.mrf_nbm_max_inundation_3day_building_footprints
FROM external.building_footprints_fema as buildings
JOIN publish.mrf_nbm_max_inundation_3day fim ON ST_INTERSECTS(fim.geom, buildings.geom);

--------------- County Summary ---------------
DROP TABLE IF EXISTS publish.mrf_nbm_max_inundation_3day_counties;
SELECT
counties.geoid,
counties.name as county,
buildings.prop_st as state,
max(fim.streamflow_cfs) AS max_flow_cfs,
avg(fim.streamflow_cfs) AS avg_flow_cfs,
max(fim.hand_stage_ft) AS max_hand_stage_ft,
avg(fim.hand_stage_ft) AS avg_hand_stage_ft,
count(buildings.build_id) AS buildings_impacted,
sum(buildings.sqfeet) AS building_sqft_impacted,
sum(CASE WHEN buildings.occ_cls = 'Agriculture' THEN 1 ELSE 0 END) AS bldgs_agriculture,
sum(CASE WHEN buildings.occ_cls = 'Assembly' THEN 1 ELSE 0 END) AS bldgs_assembly,
sum(CASE WHEN buildings.occ_cls = 'Commercial' THEN 1 ELSE 0 END) AS bldgs_commercial,
sum(CASE WHEN buildings.occ_cls = 'Education' THEN 1 ELSE 0 END) AS bldgs_education,
sum(CASE WHEN buildings.occ_cls = 'Government' THEN 1 ELSE 0 END) AS bldgs_government,
sum(CASE WHEN buildings.occ_cls = 'Industrial' THEN 1 ELSE 0 END) AS bldgs_industrial,
sum(CASE WHEN buildings.occ_cls = 'Residential' THEN 1 ELSE 0 END) AS bldgs_residential,
sum(CASE WHEN buildings.occ_cls = 'Utility and Misc' THEN 1 ELSE 0 END) AS bldgs_utility_msc,
sum(CASE WHEN buildings.occ_cls = 'Other' THEN 1 WHEN buildings.occ_cls = 'Unclassified' THEN 1 WHEN buildings.occ_cls IS NULL THEN 1 ELSE 0 END) AS bldgs_other,
to_char('1900-01-01 00:00:00'::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS reference_time,
to_char(now()::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS update_time,
counties.geom
INTO publish.mrf_nbm_max_inundation_3day_counties
FROM derived.counties AS counties
JOIN derived.channels_county_crosswalk AS crosswalk ON counties.geoid = crosswalk.geoid
JOIN publish.mrf_nbm_max_inundation_3day AS fim on crosswalk.feature_id = fim.feature_id
JOIN publish.mrf_nbm_max_inundation_3day_building_footprints AS buildings ON crosswalk.feature_id = buildings.feature_id
GROUP BY counties.geoid, counties.name, counties.geom, buildings.prop_st;

-------------- HUCS Summary ---------------
DROP TABLE IF EXISTS publish.mrf_nbm_max_inundation_3day_hucs;
SELECT
hucs.huc8,
TO_CHAR(hucs.huc8, 'fm0000000000') AS huc8_str,
max(fim.streamflow_cfs) AS max_flow_cfs,
avg(fim.streamflow_cfs) AS avg_flow_cfs,
max(fim.hand_stage_ft) AS max_hand_stage_ft,
avg(fim.hand_stage_ft) AS avg_hand_stage_ft,
count(buildings.build_id) AS buildings_impacted,
sum(buildings.sqfeet) AS building_sqft_impacted,
sum(CASE WHEN buildings.occ_cls = 'Agriculture' THEN 1 ELSE 0 END) AS bldgs_agriculture,
sum(CASE WHEN buildings.occ_cls = 'Assembly' THEN 1 ELSE 0 END) AS bldgs_assembly,
sum(CASE WHEN buildings.occ_cls = 'Commercial' THEN 1 ELSE 0 END) AS bldgs_commercial,
sum(CASE WHEN buildings.occ_cls = 'Education' THEN 1 ELSE 0 END) AS bldgs_education,
sum(CASE WHEN buildings.occ_cls = 'Government' THEN 1 ELSE 0 END) AS bldgs_government,
sum(CASE WHEN buildings.occ_cls = 'Industrial' THEN 1 ELSE 0 END) AS bldgs_industrial,
sum(CASE WHEN buildings.occ_cls = 'Residential' THEN 1 ELSE 0 END) AS bldgs_residential,
sum(CASE WHEN buildings.occ_cls = 'Utility and Misc' THEN 1 ELSE 0 END) AS bldgs_utility_msc,
sum(CASE WHEN buildings.occ_cls = 'Other' THEN 1 WHEN buildings.occ_cls = 'Unclassified' THEN 1 WHEN buildings.occ_cls IS NULL THEN 1 ELSE 0 END) AS bldgs_other,
to_char('1900-01-01 00:00:00'::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS reference_time,
to_char(now()::timestamp without time zone, 'YYYY-MM-DD HH24:MI:SS UTC') AS update_time,
hucs.geom
INTO publish.mrf_nbm_max_inundation_3day_hucs
FROM derived.huc8s_conus AS hucs
JOIN derived.featureid_huc_crosswalk AS crosswalk ON hucs.huc8 = crosswalk.huc8
JOIN publish.mrf_nbm_max_inundation_3day AS fim on crosswalk.feature_id = fim.feature_id
JOIN publish.mrf_nbm_max_inundation_3day_building_footprints AS buildings ON crosswalk.feature_id = buildings.feature_id
GROUP BY hucs.huc8, hucs.geom;
Loading