BigQuery Left Join основано на условии st_dwithin, действующем как внутреннее соединение - PullRequest
0 голосов
/ 09 ноября 2018

Мне нужна помощь со следующим ...

Я создал запрос, который должен объединять записи из другой таблицы на основе определенного расстояния между двумя координатами. Я заканчиваю с таблицей, которая имеет только записи с соответствующими именами местоположения (как внутреннее соединение). Мне нужно, чтобы каждая запись в table_customer_x и locationname была нулевой, если расстояние между любым местоположением для этого клиента> 250.

Запрос, который я создал:

 SELECT t.customerid, t.geolatitude, t.geolongitude, tt.locationname
 FROM `table_customer_x` t
 LEFT JOIN  `table_location` tt  
 on ST_DWITHIN(ST_GEOGPOINT(t.geoLatitude,t.geoLongitude), ST_GEOGPOINT(tt.latitude, tt.longitude), 250)
 where tt.customer_id= 204
 and t.timestamp > "2016-01-01"
 and tt.latitude <= 90 and tt.latitude >= -90

table_customer_x выглядит так:

timestamp             geoLatitude       geoLongitude    
2018-01-01 00:00:00       52.000             4.000

table_location выглядит так:

latitude       longitude       name      customer_id
 52.010          4.010      hospital x     204

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Это могла быть ошибка BigQuery, похоже, она сейчас исправлена.

Геопространственное внешнее объединение еще не реализовано, поэтому этот запрос должен завершиться с сообщением LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join.

Обходной путь должен симулировать внешнее соединение, используя внутреннее соединение: сделайте внутреннее соединение, затем объедините с несопоставленными строками на левой стороне. Для правильной работы требуется какой-то уникальный ключ на внешней стороне, я не уверен, есть ли он у вас в table_customer_x.

0 голосов
/ 09 ноября 2018

[Почему] левое соединение BigQuery на основе условия st_dwithin, действующего как внутреннее соединение

В BigQuery Spatial JOIN реализованы для операторов INNER JOIN и CROSS JOIN со следующими стандартными функциями предикатов SQL:

ST_DWithin
ST_Intersects
ST_Contains
ST_Within
ST_Covers
ST_CoveredBy
ST_Equals
ST_Touches   

Таким образом, вы не можете ожидать, что LEFT JOIN будет работать должным образом в вашем случае - вместо этого - ваш левый JOIN «конвертируется» в CROSS JOIN с фильтром в условии ON, перемещенным в условие Where
Таким образом, результат, который вы видите, как и ожидалось

Резюме - вам просто нужно переписать ваш запрос: o)

Вы можете попробовать что-то подобное ниже, чтобы обойти (не проверено - просто возможное направление для вас)

#standardSQL
SELECT tt.customer_id, t.geolatitude, t.geolongitude, tt.name
FROM `project.dataset.table_customer_x` t
JOIN  `project.dataset.table_location` tt  
ON ST_DWITHIN(ST_GEOGPOINT(t.geoLatitude,t.geoLongitude), ST_GEOGPOINT(tt.latitude, tt.longitude), 250)
UNION ALL
SELECT tt.customer_id, t.geolatitude, t.geolongitude, tt.name
FROM `project.dataset.table_customer_x` t
JOIN  `project.dataset.table_location` tt  
ON NOT ST_DWITHIN(ST_GEOGPOINT(t.geoLatitude,t.geoLongitude), ST_GEOGPOINT(tt.latitude, tt.longitude), 250)
WHERE tt.customer_id= 204
AND t.timestamp > "2016-01-01"
AND tt.latitude <= 90 AND tt.latitude >= -90
...