дистанционные вычисления в запросах mysql

Я должен запросить базу данных из тысяч записей и заказать это на расстоянии от указанной точки.

Проблема в том, что каждая запись имеет широту и долготу, и мне нужно будет получить каждую запись, чтобы вычислить ее расстояние. С большой базой данных я не хочу извлекать каждую строку, это может занять некоторое время.

Есть ли способ построить это в запросе mysql, так что мне нужно всего лишь получить последние 15 записей.

Например

`SELECT events.id, caclDistance($latlng, events.location) AS distance FROM events ORDER BY distance LIMIT 0,15` function caclDistance($old, $new){ //Calculates the distance between $old and $new } 

Вариант 1: выполните расчет в базе данных, переключившись на базу данных, поддерживающую GeoIP.

Вариант 2: Сделайте расчет в базе данных с использованием хранимой процедуры следующим образом:

 CREATE FUNCTION calcDistance (latA double, lonA double, latB double, LonB double) RETURNS double DETERMINISTIC BEGIN SET @RlatA = radians(latA); SET @RlonA = radians(lonA); SET @RlatB = radians(latB); SET @RlonB = radians(LonB); SET @deltaLat = @RlatA - @RlatB; SET @deltaLon = @RlonA - @RlonB; SET @d = SIN(@deltaLat/2) * SIN(@deltaLat/2) + COS(@RlatA) * COS(@RlatB) * SIN(@deltaLon/2)*SIN(@deltaLon/2); RETURN 2 * ASIN(SQRT(@d)) * 6371.01; END// 

Если у вас есть индекс по широте и долготе в вашей базе данных, вы можете уменьшить количество вычислений, которые необходимо вычислить, выработав исходный ограничивающий прямоугольник в PHP ($ minLat, $ maxLat, $ minLong и $ maxLong) и ограничивая строки к подмножеству ваших записей на основе этого (WHERE широта BETWEEN $ minLat AND $ maxLat И долгота МЕЖДУ $ minLong И $ maxLong). Затем MySQL нужно выполнить расчет расстояния для этого подмножества строк.

Если вы просто используете хранимую процедуру для вычисления расстояния), то SQL все равно придется просматривать каждую запись в вашей базе данных и вычислять расстояние для каждой записи в вашей базе данных, прежде чем она сможет решить, вернуть ли эту строку или отбросить ее ,

Поскольку вычисление относительно медленное для выполнения, было бы лучше, если бы вы могли уменьшить набор строк, которые нужно вычислить, исключая строки, которые явно будут выходить за пределы требуемого расстояния, так что мы выполняем только дорогостоящий расчет для меньшее количество строк.

Если вы считаете, что то, что вы делаете, это в основном рисование круга на карте, сосредоточенное на вашей начальной точке и с радиусом расстояния; то формула просто определяет, какие строки попадают в этот круг … но все равно приходится проверять каждую строку.

Использование ограничивающей рамки – это рисовать квадрат на карте сначала левым, правым, верхним и нижним краями на соответствующем расстоянии от нашей центральной точки. Затем наш круг будет нарисован внутри этого ящика, с точками «Самый северный», «Самый высокий», «Самой самый» и «Самый западный» на круге, касающемся границ окна. Некоторые строки выйдут за пределы этого поля, поэтому SQL даже не пытается вычислить расстояние для этих строк. Он вычисляет только расстояние для строк, попадающих в ограничительную рамку, чтобы увидеть, попадают ли они в круг.

Внутри вашего PHP (предположим, что вы используете PHP из имени переменной $), мы можем использовать очень простой расчет, который будет определять минимальную и максимальную широту и долготу на основе нашего расстояния, а затем установить эти значения в предложении WHERE вашего SQL заявление. Это действительно наша коробка, и все, что выходит за ее пределы, автоматически отбрасывается без необходимости фактически вычислять свое расстояние.

Это хорошее объяснение этого (с PHP-кодом) на сайте Movable Type, которое должно быть важным для того, чтобы кто-либо планировал выполнять любую работу GeoPositioning в PHP.

EDIT Значение 6371.01 в хранимой процедуре calcDistance – это множитель, который даст вам результат в километрах. Используйте соответствующие альтернативные множители, если вы хотите получить мили, морские мили, метры, что угодно

 SELECT events.id FROM events ORDER BY pow((lat - pointlat),2) + pow((lon - pointlon),2) ASC LIMIT 0,15 

Вам не нужно вычислять абсолютное расстояние в метрах, используя радиус земли и т. Д.

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

Я думаю, что хранимые процедуры – это то, что вы ищете.

Если ваш вопрос – это вопрос «найти мой ближайший» или «поиск магазина», вы можете использовать Google для этих условий. Как правило, этот тип данных сопровождается почтовым кодом некоторого описания, и можно сузить список (как указывает Марк-разработчик) путем ассоциации с почтовым кодом.

Каждый случай отличается, и это может не относиться к вам, просто бросая его туда.