ST_EXTENT 或 BigQuery 中的 ST_ENVELOPE?

ST_EXTENT or ST_ENVELOPE in BigQuery?

我想要 BigQuery 中 ST_EXTENTST_ENVELOPE 的等效项,但我找不到进行此查询的方法 运行:

SELECT REGEXP_EXTRACT(name, ', (..)') state
  , ST_EXTENT(ARRAY_AGG(urban_area_geom)) corners
  , COUNT(*) cities
FROM `bigquery-public-data.geo_us_boundaries.urban_areas`
GROUP BY state

此查询的所需结果是一个边界框列表,以覆盖美国各地的所有城市地区,并按州分组。

我创建了一个功能请求以获得 ST_EXTENT() 的本机实现。请添加您的投票和您为什么需要此功能的证据,以便团队可以确定优先级并让您了解任何进展:

同时,我能提供的最佳解决方案:

  • fhoffa.x.st_bounding_box():一个朴素的边界框 UDF。

这样使用:

SELECT REGEXP_EXTRACT(name, ', (..)') state
  , fhoffa.x.st_bounding_box(ARRAY_AGG(urban_area_geom)).polygon 
  , COUNT(*) urban_areas
FROM `bigquery-public-data.geo_us_boundaries.urban_areas`
GROUP BY state

其背后的代码:

CREATE OR REPLACE FUNCTION fhoffa.x.st_bounding_box(arr ANY TYPE) AS ((
  SELECT AS STRUCT *
    , ST_MakePolygon(ST_GeogFromText(FORMAT('LINESTRING(%f %f,%f %f,%f %f,%f %f)',minlon,minlat,maxlon,minlat,maxlon,maxlat,minlon, maxlat))) polygon
  FROM (
    SELECT MIN(m.min_x) minlon, MAX(m.max_x) maxlon , MIN(m.min_y) minlat, MAX(m.max_y) maxlat
    FROM (
      SELECT 
        (SELECT AS STRUCT MIN(x) min_x, MAX(x) max_x, MIN(y) min_y, MAX(y) max_y FROM UNNEST(coords)) m
      FROM (
        SELECT ARRAY(
          SELECT STRUCT(
            CAST(SPLIT(c, ', ')[OFFSET(0)] AS FLOAT64) AS x, 
            CAST(SPLIT(c, ', ')[OFFSET(1)] AS FLOAT64) AS y
          )
          FROM UNNEST(REGEXP_EXTRACT_ALL(ST_ASGEOJSON(geog), r'\[([^[\]]*)\]')) c
        ) coords
        FROM UNNEST(arr) geog
      )
    )
  )
))

备注:

  • 需要额外的努力才能使其适用于跨越 -180 线的几何图形。

  • 由于测地线边缘,函数结果不是真正的边界框,即 ST_Covers(box, geom) 可能 return FALSE。

  • 在上图中,我并不期望每个州都被完全覆盖,只是它的城市地区。因此,如果那些未覆盖的角落没有市区,则边界框是正确的。

  • 以下多边形构造将为您提供精确的 "rectangles",但它们的结构要复杂得多。

ST_GEOGFROMGEOJSON(
  FORMAT('{"type": "Polygon", "coordinates": [[[%f,%f],[%f,%f],[%f,%f],[%f,%f],[%f, %f]]]}'
  , minlon,minlat,maxlon,minlat,maxlon,maxlat,minlon,maxlat,minlon,minlat)
)

期待您的意见和建议。