Afternoon,
I am having some difficulty getting my head around this problem. I have a MySQL table with a list of UK Post Codes and their longitude and latitude values. I want to be able to carry out a search on the table that will find the closest postcode to the a given long/lat pair.
The query I have been attempting to use is:
"SELECT id, outcode AS thecode, @la := MATCH(lat) AGAINST(?) AS score_lat, @ln := MATCH(lng) AGAINST(?) AS score_lng, @la + @ln AS score_total FROM postcodes ORDER BY score_total DESC LIMIT 10
This however just returns what appears to be random postcodes, for example with Lat: 55.775549 and Long: -4.047556
Array
(
[0] => Array
(
[id] => 929
[thecode] => FK14
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[1] => Array
(
[id] => 2785
[thecode] => UB3
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[2] => Array
(
[id] => 993
[thecode] => G70
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[3] => Array
(
[id] => 2849
[thecode] => WC2B
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[4] => Array
(
[id] => 1057
[thecode] => GU29
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[5] => Array
(
[id] => 2913
[thecode] => WS13
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[6] => Array
(
[id] => 1121
[thecode] => HP20
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[7] => Array
(
[id] => 1185
[thecode] => IG6
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[8] => Array
(
[id] => 1249
[thecode] => IV25
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
[9] => Array
(
[id] => 1313
[thecode] => KA8
[score_lat] => 0
[score_lng] => 0
[score_total] => 0
)
)
The schema of the database is:
CREATE TABLE `postcodes` (
`id` int(11) NOT NULL auto_increment,
`outcode` varchar(4) NOT NULL,
`lat` varchar(20) NOT NULL,
`lng` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
FULLTEXT KEY `lat` (`lat`),
FULLTEXT KEY `lng` (`lng`)
) ENGINE=MyISAM AUTO_INCREMENT=2975 DEFAULT CHARSET=latin1 AUTO_INCREMENT=2975 ;
I hope someone can help! If you need any more information please just ask…
Thanks,
tip2tail
The MySQL
MATCH()function is used for full-text searches to “match” on character strings. (So it’s not surprising that its returning a value of zero.)If by “closest” you mean you want to calculate the distance (as measured ‘as the crow flies’), between two points on a map, with coordinates given in (decimal degrees) latitude and longitude, you’d really need to use a great circle distance (GCD) calculation.
http://en.wikipedia.org/wiki/Great-circle_distance
You can skip all those gory details, and just make use of my implementation. Below is an excerpt from the SELECT list of one of my SQL statements, this expression calculates the distance (in miles) between two points…
In this example,
d1represents the origin point, andd2represents the destination point. Thelatitudeandlongitudeare supplied as DECIMAL values.With a single “known” point for
d1, I can order by this expression, to get the “closest”d2first. (For multiple origin points, I can order byd1.id, then by this expression to get the closestd2first for eachd1. But enough about my problem…I copied the query from your question and modified it (below). Basically, I removed the “score” columns, and replaced it with an expression that does a distance calculation:
In this case the
@d1_variables (assigned from bind variables) are the latitude and longitude of your “known” point. For each row in yourpostcodestable (which I aliased asd2for convenience), this expression calculates the distance between the lat/long in the table and the “known” point.NOTE: the inline view aliased as
vis just there so you can bind the latitude just once, and assign the values to user variables that can be referenced. That inline view can be omitted, and you can see where you would need to bind the latitude twice.NOTE: this calculates distance in “miles”. You can easily get distance in kilometers (km) by substituting a different value in place of the
3958.82constant.NOTE: It’s not necessary to return the distance; you could just put that expression in the ORDER BY clause if you’re only interested in returning the 10 closest in order by distance, e.g.
Please let me know if you are looking for something other than distance between two points, because in that case, this answer is really of no help to you.