SQL-запрос для Выполнения Поиска Радиуса на основе Долготы Широты

Намерение (x == 10):

if (x = 10) {
    //Do something
}

я думал, что никогда не буду делать эту ошибку сам, но я на самом деле недавно сделал это.

12
задан Muhammad Waheed 18 November 2019 в 14:01
поделиться

4 ответа

ЕСТЬ НИЧЕГО НЕПРАВИЛЬНО с этим query?

На мой взгляд, предложение WHERE будет медленным из-за задействованной математики, а использование функций в предложении WHERE предотвратит использование базой данных индекса для ускорения запроса - так что, по сути, вы будете исследуйте каждый ресторан в базе данных и выполняйте математические вычисления по дуге большого круга для каждой строки каждый раз, когда вы делаете запрос.

Лично я бы вычислил координаты TopLeft и BottomRight квадрата (которые нужно только грубо вычислить используя pythagoras) со сторонами, равными диапазону, который вы ищете, а затем выполните более сложный тест предложения WHERE для меньшего подмножества записей, которые находятся в пределах этого квадрата широты / долготы.

С индексом широты и долготы в поле база данных запрос

WHERE     MyLat >= @MinLat AND MyLat <= @MaxLat
      AND MyLong >= @MinLong AND MyLong <= @MaxLong

должен быть очень эффективным

(обратите внимание, что я не знаю конкретно MySQL, только MS SQL)

13
ответ дан 2 December 2019 в 20:18
поделиться

Вы можете создать для своей таблицы индекс SPATIAL , чтобы ускорить поиск.

Для этого добавьте в свою таблицу столбец POINT :

ALTER TABLE restaurant ADD coords POINT NOT NULL;

CREATE SPATIAL INDEX sx_restaurant_coords ON restaurant (coords);

SELECT  *
FROM    restaurant
WHERE   MBRContains(coords, LineString(Point(583734 - 1609, 4507223 - 1609), Point(583734 + 1609, 4507223 + 1609))
        AND GLength(LineString(Point(583734, 4507223), coords)) <= 1609

Вам следует сохранить координаты как UTM координаты в одной зоне.

3
ответ дан 2 December 2019 в 20:18
поделиться

Если ваши данные находятся в базе данных SQL-сервера, вы можете использовать это:

CREATE PROC up_FindZipCodesWithinRadius

    @ZipCode char(5) ,
    @GivenMileRadius int
AS
SET NOCOUNT ON

DECLARE @lat1 float, 
    @long1 float

SELECT  @lat1= latitude,
    @long1 = longitude 
FROM ZipSource
WHERE zipcode = @ZipCode

SELECT ZipCode ,DistanceInMiles
FROM
(
    SELECT  ZipCode,3958.75 * ( Atan(Sqrt(1 - power(((Sin(@Lat1/57.2958) * Sin(latitude/57.2958)) + 
            (Cos(@Lat1/57.2958) * Cos(latitude/57.2958) * Cos((longitude/57.2958) - (@Long1/57.2958)))), 2)) / 
            ((Sin(@Lat1/57.2958) * Sin(latitude/57.2958)) + (Cos(@Lat1/57.2958) * Cos(latitude/57.2958) * 
            Cos((longitude/57.2958) - (@Long1/57.2958)))))) as DistanceInMiles
FROM ZipSource
) a
WHERE a.DistanceInMiles <= @GivenMileRadius
--AND ZipCode <> @ZipCode
ORDER BY DistanceInMiles

GO

EXEC up_FindZipCodesWithinRadius '35085',20
GO

DROP PROC up_FindZipCodesWithinRadius
0
ответ дан 2 December 2019 в 20:18
поделиться

Используйте функцию, например, ту , которую я разместил здесь .

Затем запросите ваши рестораны, например, чтобы получить все в радиусе 5 миль

select * from restaurants 
  where dbo.udf_Haversine(latitude, longitude, @lat, @long) < 5

Это отлично работает с данными почтового индекса.

0
ответ дан 2 December 2019 в 20:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: