Как получить местоположение по широте и долготе в T-SQL?

#sql #sql-server #tsql #inner-join #spatial

#sql #sql-server #tsql #внутреннее соединение #пространственный

Вопрос:

У меня есть таблица сопоставления LocationID вместе с их значением широты и долготы центра, как показано ниже-

 | Location Id | Center_lat | Center_long |
|-------------|------------|-------------|
| 1           | 50.546     | 88.344      |
| 2           | 48.546     | 86.344      |
| 3           | 52.546     | 89.344      |
  

У меня есть другая таблица, в которой я получаю непрерывные данные о местоположении с широтой и долготой для пользователя, как показано ниже —

  --------- ------------ ------------- 
| User Id | Center_lat | Center_long |
 --------- ------------ ------------- 
|     101 |     50.446 |      88.314 |
|     102 |     48.446 |      86.314 |
|     103 |     52.446 |      89.314 |
 --------- ------------ ------------- 
  

Я хочу получить LocationID всех пользователей, если их значения широты и долготы находятся в пределах 1000 метров от значений длины широты, соответствующих идентификатору местоположения. Как я могу это сделать в T-SQL?

Итоговая таблица должна выглядеть следующим образом —

  --------- ------------ ------------- ------------ 
| User Id | Center_lat | Center_long | LocationId |
 --------- ------------ ------------- ------------ 
|     101 |     50.546 |      88.344 |          1 |
|     102 |     48.546 |      86.344 |          2 |
|     103 |     52.546 |      89.344 |          3 |
 --------- ------------ ------------- ------------ 
  

Комментарии:

1. Есть ли причина, по которой вы не используете geography тип, а не сохраняете lat / long в отдельных столбцах?

2. learn.microsoft.com/en-us/sql/t-sql/spatial-geography/…

Ответ №1:

Вы можете использовать преобразование пар широта / долгота в geography объекты, а затем использовать stdistance() :

 select u.*, l.location_id
from users u
inner join locations l
    on geography::point(u.center_lat, u.center_long, 4326).stdistance(geography::point(l.center_lat, l.center_long, 4326)) < 1000
  

Обратите внимание, что было бы гораздо эффективнее хранить эту информацию как point s для начала.