Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Pobliskie miasta
Forum PHP.pl > Forum > Bazy danych > MySQL
Robert007
Witam, mam w bazie miasta z podanymi lat i lng i chciałbym na podstawie danej pozycji lat lng sprawdzić najbliższe miasta i obliczyć ile w danej odległości jest kilometrów.

Co chcę uzyskać? Mam tak:
1. Podaje do zapytania SQL moje pozycje (np. lat: 53.1351082 lng: 17.90514870000004)
2. W bazie wszystkie miasta mają swoją pozycję lat i lng i chcę by mi wyświetliło X miast tylko najbliższych do podanej pozycji.
3. Policzenie odległości km ile do danego miasta jest od podanej pozycji w linii prostej.

Zapewne trzeba użyć jakiś specyficznych funkcji MySQL ale niestety nie wiem jak się za to zabrać i jakie funkcję mi pomogą.
Liczę na waszą pomoc.
trueblue
Zapewne nie.

http://stackoverflow.com/questions/27928/c...versine-formula
Robert007
Wydaję mi się że działa poprawnie, wrzucam poniżej rozwiązanie:
  1. SELECT location, (6371 * acos(cos(radians(52.3957877)) * cos(radians(coordinates_lat)) * cos(radians(16.7491037) - radians(coordinates_lng)) + sin( radians(52.3957877)) * sin(radians(coordinates_lat)))) AS distanta
  2. FROM `TABELA` WHERE coordinates_lat <> '' AND coordinates_lng <> '' HAVING distanta < 50 ORDER BY distanta ASC


W razie nie będzie działać jak powinno to napiszę Tutaj.
Dzięki!


trueblue
Na pewno nie HAVING, warunek powinien być w WHERE.
Robert007
Jest błąd SQL wtedy jak dam AND zamiast HAVING, w ogóle co to za liczba 6371? Bo tam nie wiem czy trzeba coś podstawić.
trueblue
Trzeba przenieść obliczenie do WHERE, wtedy bez ORDER tak:
  1. SELECT location
  2. FROM `TABELA` WHERE coordinates_lat <> '' AND coordinates_lng <> '' AND (6371 * acos(cos(radians(52.3957877)) * cos(radians(coordinates_lat)) * cos(radians(16.7491037) - radians(coordinates_lng)) + sin( radians(52.3957877)) * sin(radians(coordinates_lat)))) < 50


lub z ORDER:
  1. SELECT location, (6371 * acos(cos(radians(52.3957877)) * cos(radians(coordinates_lat)) * cos(radians(16.7491037) - radians(coordinates_lng)) + sin( radians(52.3957877)) * sin(radians(coordinates_lat)))) AS distanta
  2. FROM `TABELA` WHERE coordinates_lat <> '' AND coordinates_lng <> '' AND (6371 * acos(cos(radians(52.3957877)) * cos(radians(coordinates_lat)) * cos(radians(16.7491037) - radians(coordinates_lng)) + sin( radians(52.3957877)) * sin(radians(coordinates_lat)))) < 50 ORDER BY distanta ASC



Cytat
var R = 6371; // Radius of the earth in km
Robert007
OK czyli przykład z "lub z ORDER:" rozumiem że jest optymalniejszy i może nie generuje tabeli tymczasowej?
trueblue
Raczej bez ORDER jest optymalniejszy i trudniej o błąd w składni obliczeń. Sortować wtedy można już bezpośrednio w kodzie, po pobraniu danych.
Sprawdź sobie optymalność poprzez EXPLAIN.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.