Вариант 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) и ограничение строк подмножеством ваших записей на основе этого (ГДЕ широта между $ minLat и $ maxLat И долгота между $ minLong И $ maxLong). Тогда MySQL нужно только выполнить расчет расстояния для этого подмножества строк.
Если вы просто используете хранимую процедуру для вычисления расстояния), тогда SQL все равно должен просмотреть каждую запись в вашей базе данных и рассчитать расстояние для каждой записи в вашей базе данных, прежде чем он сможет решить, следует ли возвращать эту строку или откажитесь от него.
Поскольку вычисления выполняются относительно медленно, было бы лучше, если бы вы могли уменьшить набор строк, которые необходимо вычислить, исключив строки, которые явно выходят за пределы требуемого расстояния, поэтому мы выполняем только дорогой расчет для меньшего количества строк.
Если вы считаете, что в основном вы рисуете круг на карте с центром в начальной точке и с радиусом расстояния; тогда формула просто определяет, какие строки попадают в этот круг ... но она все равно должна проверять каждую строку.
Использование ограничивающей рамки похоже на то, чтобы сначала нарисовать квадрат на карте с левым, правым, верхним и нижним краями на соответствующем расстоянии от нашей центральной точки. Затем наш круг будет нарисован внутри этого прямоугольника, а самые северные, самые восточные, самые южные и самые западные точки на круге касаются границ прямоугольника. Некоторые строки будут выходить за рамки этого поля, поэтому SQL даже не пытается вычислить расстояние для этих строк. Он рассчитывает расстояние только для тех строк, которые попадают в ограничивающую рамку, чтобы увидеть, попадают ли они и в круг.
В вашем PHP (предположим, вы используете PHP из имени переменной $), мы можем использовать очень простой расчет, который определяет минимальную и максимальную широту и долготу на основе нашего расстояния, а затем установить эти значения в предложении WHERE. вашего оператора SQL. Это фактически наша коробка, и все, что выпадает за пределы этого, автоматически отбрасывается без необходимости фактически вычислять его расстояние.
На веб-сайте Movable Type есть хорошее объяснение этого (с использованием PHP-кода), которое должно быть важным чтением для любого, кто планирует выполнять какую-либо работу с геопозицией в PHP.
EDIT
Значение 6371.01 в хранимой процедуре calcDistance является множителем, который возвращает результат в километрах. Используйте соответствующие альтернативные множители, если хотите, чтобы в милях, морских милях, метрах и т.д.