Den hurtigste måde at gøre dette på er at bruge de geospatiale udvidelser til MySQL, hvilket burde være nemt nok, da du allerede bruger en MyISAM-tabel. Dokumentationen for disse udvidelser kan findes her:http:/ /dev.mysql.com/doc/refman/5.6/en/spatial-extensions.html
Tilføj en ny kolonne med en POINT-datatype:
ALTER TABLE `adverts`
ADD COLUMN `geopoint` POINT NOT NULL AFTER `longitude`
ADD SPATIAL KEY `geopoint` (`geopoint`)
Du kan derefter udfylde denne kolonne fra dine eksisterende bredde- og længdegradsfelter:
UPDATE `adverts`
SET `geopoint` = GeomFromText(CONCAT('POINT(',`latitude`,' ',`longitude`,')'));
Det næste trin er at oprette en afgrænsningsboks baseret på den inputbredde- og længdegrad, der vil blive brugt i din WHERE
klausul som en CONTAINS
begrænsning. Du skal bestemme et sæt X,Y POINT
koordinater, der fungerer til dine krav baseret på det ønskede søgeområde og givet udgangspunkt.
Din sidste forespørgsel vil søge efter alle POINT
data, der er inden for din søgning POLYGON
, og du kan derefter bruge en afstandsberegning til at forfine og sortere dine data yderligere:
SELECT a.*,
ROUND( SQRT( ( ( (adverts.latitude - '53.410778') * (adverts.latitude - '53.410778') ) * 69.1 * 69.1 ) + ( (adverts.longitude - '-2.97784') * (adverts.longitude - '-2.97784') * 53 * 53 ) ), 1 ) AS distance
FROM adverts a
WHERE a.type_id = 3
AND CONTAINS(a.geopoint, GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))'))
HAVING distance < 25
ORDER BY distance DESC
LIMIT 0, 30
Bemærk, at GeomFromText('Polygon((0 0,0 3,3 3,3 0,0 0))')
i ovenstående vil ikke virke , skal du erstatte koordinaterne med gyldige punkter omkring din søgestart. Hvis du forventer, at lat/længden ændrer sig, bør du overveje at bruge en trigger til at beholde POINT
data og tilhørende SPATIAL KEY
opdateret. Med store datasæt bør du se markant forbedret ydeevne i forhold til at beregne en afstand for hver post og filtrering ved hjælp af en HAVING
klausul. Jeg har personligt defineret funktioner til brug ved bestemmelse af afstanden og oprettelse af den grænsende POLYGON
.