Вариант 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 географска ширина МЕЖДУ $minLat И $maxLat И дължина МЕЖДУ $minLong И $maxLong). Тогава MySQL трябва само да изпълни изчислението на разстоянието за това подмножество от редове.
Ако просто използвате съхранена процедура за изчисляване на разстоянието), тогава SQL все още трябва да прегледа всеки запис във вашата база данни и да изчисли разстоянието за всеки запис във вашата база данни, преди да може да реши дали да върне този ред или да го изхвърли .
Тъй като изчислението е сравнително бавно за изпълнение, би било по-добре, ако можете да намалите набора от редове, които трябва да бъдат изчислени, елиминирайки редове, които очевидно ще попадат извън необходимото разстояние, така че да изпълняваме само скъпото изчисление за по-малък брой редове.
Ако смятате, че това, което правите, е основно рисуване на кръг върху карта, центриран върху вашата начална точка и с радиус на разстояние; тогава формулата просто идентифицира кои редове попадат в този кръг... но все пак трябва да проверява всеки отделен ред.
Използването на ограничителна кутия е като да начертаете първо квадрат на картата с левия, десния, горния и долния ръб на подходящото разстояние от нашата централна точка. След това нашият кръг ще бъде начертан в това поле, като най-северната, най-източната, най-южната и най-западната точки на кръга ще докосват границите на полето. Някои редове ще попаднат извън това поле, така че SQL дори не си прави труда да се опитва да изчисли разстоянието за тези редове. Той изчислява разстоянието само за тези редове, които попадат в рамките на ограничителната кутия, за да види дали и те попадат в кръга.
Във вашия PHP (предполагам, че изпълнявате PHP от името на променлива $), можем да използваме много просто изчисление, което изработва минималната и максималната ширина и дължина въз основа на нашето разстояние, след което да зададем тези стойности в клаузата WHERE на вашия SQL изявление. Това всъщност е нашата кутия и всичко, което попада извън това, се изхвърля автоматично, без да е необходимо действително да се изчислява разстоянието му.
Има добро обяснение за това (с PHP код) в Movable Type уебсайт това би трябвало да е важно четиво за всеки, който планира да извършва някаква работа по геопозициониране в PHP.
РЕДАКТИРАНЕ Стойността 6371.01 в съхранената процедура calcDistance е множител, за да ви даде върнат резултат в километри. Използвайте подходящи алтернативни множители, ако искате да получите мили, морски мили, метри, каквото и да е