Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Lokalizacja obiektu po wspolrzednych
Forum PHP.pl > Forum > Bazy danych > MySQL
prowseed
Witam,
mam dosc nietypowy problem i nie wiem jak sobie z nim poradzic. Dodam, ze uzycie bazy z zalozenia bedzie duze i boje sie, ze zrobie to nieoptymalnie...
Ale do rzeczy: Mam tabelę z listą obiektów, która wygląda tak:

[ id | name ]

oraz tabelę właściwości, która prezentuje się tak:

[ id | object_id | attribute | value ]

Atrybutów dla jednego object_id jest bardzo dużo, między innymi znajduje się tam latitude i longitude, czyli przykładowe wiersze:

[ 45 | 11 | lat | 55.423423 ]
[ 46 | 11 | lng | 21.102234 ]


Baza w taki sposób była budowana dość długo, a teraz ma dojść, że tak powiem feature lokalizacji obiektów za pomocą funkcji haversina, która wykonuje się mniej więcej tak:
haversine_distance(lat_0, lng_0, lat, lng) < 40
Zwraca ona true lub false w zależności od tego, czy dany punkt lat,lng znajduje się w promienu 40 kilometrów od lat_0,lng_0

Zdaję sobie sprawę, że jest to nieoptymalne i najłatwiejszą rzeczą byłoby posiadanie tabeli obiektów w postaci [ id | name | lat | lng ] ( co w ostateczności uczynię )
ale jest jak jest, do tego są już wszystkie mechanizmy i bardziej mi się na chwilę obecną czasowo opłaca zrobić nieludzkie zapytanie niż zmieniać konstrukcję aplikacji.
Tylko... Nie wiem jak owe zapytanie zbudować :/
Do tej pory zapytania wyglądały mniej więcej jakoś tak:

  1. SELECT id
  2. FROM objects
  3. INNER JOIN objects_attr m1
  4. ON ( objects.id = m1.object_id )
  5. WHERE
  6. objects.id > 2233
  7. AND ( m1.attribute = 'lat' AND m1.value < 60 )
  8. AND ( m1.attribute = 'lon' AND m1.value < 30 )


Czy jest jakaś możliwość połączenia tego zapytania z funkcją haversina która de facto musi sprawdzić obie wartości value występujące powyżej?

Jeżeli się nie jasno wyraziłem, to mówić- doprecyzuję, sam nie jestem w stanie sprawdzić, bo już mnie głowa boli od myślenia :s
Dzięki za pomoc.
kayman
nie wiem czy to dobrze zrozumiałem

  1. SELECT id
  2. FROM objects
  3. INNER JOIN objects_attr m1
  4. ON ( objects.id = m1.object_id AND ( m1.attribute = 'lat' AND m1.value < 60 ) AND ( m1.attribute = 'lon' AND m1.value < 30 ))
  5. WHERE
  6. objects.id > 2233
prowseed
Ok, tylko nie zapomnij jeszcze o tej nieszczęsnej funkcji ; )

haversine_distance(lat_0, lng_0, lat, lng) < 40

gdzie lat to value dla attribute = lat, a lng to value dla attribute = lng
Crozin
Jak sam zauważyłeś, struktura tabeli jest beznadziejna i raczej powinieneś dążyć do jak najszybszego poprawienia jej. Jednak, jeżeli to nie jest możliwe możesz zrobić następującą "protezę":
1. Do tabeli z obiektami dodaj kolumny longitude, latitude z założonym odpowiednim indeksem. Kolumny te będą służyć wyłącznie za kopię danych z tabeli z atrybutami. Dzięki temu cała reszta aplikacji będzie mogła działać tak jak do tej pory, a wyszukiwanie na podstawie odległości będzie mogło korzystać z "normalnej" struktury.
2. Utwórz triggery AFTER INSERT|UPDATE|DELETE dla tabeli z atrybutami, które będą aktualizowały dane w tabeli z obiektami.

O ile aplikacja nie jest napisana w jakiś tragiczny sposób, taka zmiana nie powinna mieć żadnego wpływu na działanie aplikacji.
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.