Как присоединиться к колонкам географии, используя ST_CONTAINS в большом запросе - PullRequest
0 голосов
/ 31 мая 2019

У меня есть одна таблица BigQuery с адресами, включая Lat / Lng и другие таблицы BQ с рабочими определениями geom, импортированными из шейп-файлов Census. Для каждой строки в таблице адресов я пытаюсь найти, какая строка geom содержит ее.

Следующий запрос, где я искал ИНДИВИДУАЛЬНЫЙ ШТ / ЛНГ, работает отлично:

SELECT SLDLST FROM `geographies.tl_2018_sldl_*` sldl WHERE ST_CONTAINS(sldl.geom, ST_GEOGPOINT(-95.221080, 38.974500));

Но когда я пытаюсь абстрагироваться в соединение, как

SELECT 
  address_id,
  SLDLST
FROM `launchpad-239920.address_standardization.temp_delete_geo_match_sample` ssgolden
LEFT JOIN `geographies.tl_2018_sldl_*` sldl ON ST_CONTAINS(sldl.geom, ST_GEOGPOINT(ssgolden.longitude, ssgolden.latitude));

Я получаю ошибку: «LEFT OUTER JOIN нельзя использовать без условия, равного равенству полей с обеих сторон объединения».

Как мне реструктурировать мой запрос на соединение, чтобы иметь возможность извлекать соответствующую географию для каждого адреса?

Ответы [ 2 ]

3 голосов
/ 31 мая 2019

Ниже для BigQuery Standard SQL

Если вы хотите сохранить не совпадающие адреса в выводе - вы можете использовать ниже

#standardSQL
WITH matched_addresses AS (
  SELECT 
    address_id,
    SLDLST
  FROM `launchpad-239920.address_standardization.temp_delete_geo_match_sample` ssgolden
  JOIN `geographies.tl_2018_sldl_X` sldl 
  ON ST_CONTAINS(sldl.geom, ST_GEOGPOINT(ssgolden.longitude, ssgolden.latitude)) 
)
SELECT * FROM matched_addresses UNION ALL 
SELECT address_id, NULL 
FROM `launchpad-239920.address_standardization.temp_delete_geo_match_sample`
WHERE NOT address_id IN (SELECT address_id FROM matched_addresses)   

, но если вы заинтересованы только в совпадении - используйте ниже одного

#standardSQL
WITH matched_addresses AS (
  SELECT 
    address_id,
    SLDLST
  FROM `launchpad-239920.address_standardization.temp_delete_geo_match_sample` ssgolden
  JOIN `geographies.tl_2018_sldl_X` sldl 
  ON ST_CONTAINS(sldl.geom, ST_GEOGPOINT(ssgolden.longitude, ssgolden.latitude)) 
)
SELECT * FROM matched_addresses  
0 голосов
/ 04 июня 2019

Решение, которое автоматически заботится о несопоставленных адресах, без необходимости UNION_ALL, который предлагает Михаил (чтобы производительность могла быть лучше):

#standardSQL
WITH addresses AS (
  SELECT *, GENERATE_UUID() uuid
  FROM `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2015`  ssgolden
  WHERE DATE(ssgolden.pickup_datetime) = '2015-10-07'
), matched_addresses AS (
  SELECT ARRAY_AGG(
      IF(
        ST_CONTAINS(sldl.zone_geom, SAFE.ST_GEOGPOINT(ssgolden.pickup_longitude, ssgolden.pickup_latitude))
        , sldl.zone_name, null)
      IGNORE NULLs LIMIT 1)[OFFSET(0)] zone_name
  FROM addresses  ssgolden
  CROSS JOIN `bigquery-public-data.new_york_taxi_trips.taxi_zone_geom`  sldl 
  GROUP BY uuid
)

SELECT zone_name, COUNT(*) c
FROM matched_addresses 
GROUP BY 1
ORDER BY c DESC

enter image description here

Теперь давайте проверим производительность в сравнении с большим набором геометрий (74 133 - весь США и более - в ответ на комментарий Майкла):

#standardSQL
WITH addresses AS (
  SELECT *, GENERATE_UUID() uuid
  FROM `bigquery-public-data.new_york_taxi_trips.tlc_yellow_trips_2015`  ssgolden
  WHERE DATE(ssgolden.pickup_datetime) = '2015-10-07'
), matched_addresses AS (
  SELECT ARRAY_AGG(
      IF(
        ST_CONTAINS(sldl.tract_geom, SAFE.ST_GEOGPOINT(ssgolden.pickup_longitude, ssgolden.pickup_latitude))
        , FORMAT('%s %s', sldl._table_suffix,sldl.lsad_name), null)
      IGNORE NULLs LIMIT 1)[OFFSET(0)] zone_name
  FROM addresses  ssgolden
  CROSS JOIN `bigquery-public-data.geo_census_tracts.census_tracts_*`   sldl 
  GROUP BY uuid
)

SELECT zone_name, COUNT(*) c
FROM matched_addresses 
GROUP BY 1
ORDER BY c DESC
...