I have a query (from Google Maps) like so:
SELECT ( 3959 * acos( cos( radians(MY_LAT) ) * cos( radians( LATITUDE ) ) *
cos( radians( LONGITUDE ) - radians(MY_LONG) ) + sin( radians(MY_LAT) ) * sin( radians(
LATITUDE ) ) ) ) AS distance
FROM zips
ORDER BY distance
I would rather this be a custom find in Cakephp, so how do I do that?
MY_LAT and MY_LONG are params passed in.
LATITUDE and LONGITUDE are columns in zips table.
You can use a behavior like the geocoder behavior ( https://github.com/dereuromark/tools/blob/2.0/Model/Behavior/GeocoderBehavior.php#L208 ) and attach it to your model with
$this->Model->Behaviors->attach('Tools.Geocoder');
and call
$this->Model->setDistanceAsVirtualField($lat, $lng, $fieldName);
this way a virtual field is attached and will retrieve and contain your distance value just like any other normal field. you can also sort/filter by that field then.
Related
I am trying to run a query that finds the places near my location, but every time I try to run it, it returns the following error:
column "distance" does not exist
If I remove distance and only leave up to the FROM posts, it returns the post id and the distance column.
But if I leave it in the original way, it returns the error.
SELECT id,
( 3959 * acos( cos( radians(-32.63) ) * cos( radians( latitude ) ) *
cos( radians( longitude ) - radians(-71.42) ) + sin( radians(-32.63) ) *
sin( radians( latitude ) ) ) ) AS distance
FROM posts
HAVING distance < 25
ORDER BY distance;
You can't use a column alias in other places in the same query. You'll have to either repeat the entire expression in your HAVING and ORDER BY or use your existing query as a sub-query and apply the HAVING and ORDER BY to the outer query, or use a CTE if your RDBMS supports it.
SELECT id, distance FROM
(SELECT id, ( 3959 * acos( cos( radians(-32.63) ) * cos( radians( latitude ) ) *
cos( radians( longitude ) - radians(-71.42) ) + sin( radians(-32.63) ) *
sin( radians( latitude ) ) ) ) AS distance FROM posts) p
WHERE distance < 25 ORDER BY distance;
you need to put CTA to order it by distance
Here is my table named "test" -
Check the snapshot here test
And then my row items: here - rowitems
I'm using the haversine formula, he is my query
SELECT *, ( 3960 * acos( cos( radians( 33.650800 ) ) *
cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians( -117.891729 ) ) +
sin( radians( 33.650800 ) ) * sin( radians( Latitude ) ) ) ) AS Distance
FROM test
For some reason the HAVING or WHERE clause is not working with Distance.
It works with Latitude or Longitude.
But when I try to do WHERE Distance < 10 or HAVING Distance < 10. It says Distance is an invalid column name.
I need to be able to do this, and make a query using Distance. Any help would be appreciated.
You cannot use calculated fields on a where or having clause. Create a view or use a subquery
Try this:
select * FROM (SELECT *, ( 3960 * acos( cos( radians( 33.650800 ) ) *
cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians( -117.891729 ) ) +
sin( radians( 33.650800 ) ) * sin( radians( Latitude ) ) ) ) AS Distance
FROM test) as T WHERE T.Distance < 10
You need to put your query into a subquery, or a view, or a CTE (common table expression).
Here is an example for your task with a CTE:
WITH cte_test (Name, Latitude, Longitude, Distance)
AS
(
SELECT Name, Latitude, Longitude,
3960 * acos(cos(radians(33.650800))
* cos(radians( Latitude ) )
* cos( radians( Longitude ) - radians( -117.891729 ) )
+ sin( radians( 33.650800 ) ) * sin( radians( Latitude ) ) ) )
AS Distance
FROM test
)
SELECT * from cte_test where Distance < 10 ;
A CTE is a kind of "temporary view". It is also a powerful instrument which can also be used for creating recursive queries.
I have a table that contains column called func_id , latitude and longitude. Im trying to get the min distance row and return the func_id by a function.
I tried:
function Get_Min_func_id($lat, $long){
$query = mysql_query("
select func_id,
MIN( 3959 * acos( cos( radians('$lat') )
* cos( radians( latitude ) )
* cos( radians( longitude ) - radians('$long') )
+ sin( radians('$lat') )
* sin( radians( latitude ) ) ) ) AS distance
from entregas
");
return #mysql_result($query, 0, 'func_id');
}
But its not working fine. It is returning only the same func_id.
This is the query that you want:
select func_id,
( 3959 * acos( cos( radians('$lat') )
* cos( radians( latitude ) )
* cos( radians( longitude ) - radians('$long') )
+ sin( radians('$lat') )
* sin( radians( latitude ) ) ) ) AS distance
from entregas
order by distance asc
limit 1;
Your query will return the minimum distance, but an arbitrary value for func_id. As a general rule, you should always have the same columns in a group by as in the select, unless you are using aggregation functions. In this case, you have an aggregation query with no group by, so there should be no additional columns.
I am trying to display a list of general stores that are near to the current map location.
Everything works fine but I just realised no matter where I pan the map to, a lot of stores that are no where near to the current map location gets call from my SQL Server DB.
Example:
I have a store which resides in Germany in the DB:
Venue Venue_Lat Venue_Lng
Bookstore 51.165712 10.451547
I am using the Haversine formulae in my Stored Procedure [GetNearbyLocations] to retrieve the stores that are suppose to be within 50 miles of the current location, say I pass in a current location as USA with a radius of 50 miles:
Radius: 50
USA Lat: 38.5554745
USA Lng: -95.6649999
The store in Germany gets called as well even though its not within the 50 miles radius. I understand and accept that the formulae is not 100% accurate but is this usual? Can anyone please kindly advice on this. Thanks.
A portion of the SProc:
DECLARE #intMilesModifier int
SET #intMilesModifier = 3959
SELECT .... some fields,
[Venue_Lat],
[Venue_Long],
(#intMilesModifier*acos(cos(radians(#dmlLat))*cos(radians(Venue_Lat))*cos(radians(Venue_Long)-radians(#dmlLng))+sin(radians(#dmlLat))*sin(radians(Venue_Lat)))) AS distance
FROM [Stores] a
WHERE (#intMilesModifier*acos(cos(radians(#dmlLat))*cos(radians(Venue_Lat))*cos(radians(Venue_Long)-radians(#dmlLng))+sin(radians(#dmlLat))*sin(radians(Venue_Lat)))) < #Radius
This PHP/MySQL PDO SQL statement uses the formula (6371 for kilometers,3959 for miles)
$stmt = $dbh->prepare("SELECT name, lat, lng, ( 3959 * acos( cos( radians(?) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS distance FROM gbstn HAVING distance < ? ORDER BY distance LIMIT 0 , 20");
// Assign parameters
$stmt->bindParam(1,$center_lat);//coordinate of center
$stmt->bindParam(2,$center_lng);//coordinate of center
$stmt->bindParam(3,$center_lat);
$stmt->bindParam(4,$radius);
You will need to modify this to suit
EDIT
You have extra calculations in your formula. I have edited my statement to show what you should have. I removed [] brackets and a from [Stores] a, don't need alias, but cant run query as I dont have SQL Server.
"SELECT Venue_Lat,Venue_Long,(#intMilesModifier * acos( cos( radians(#dmlLat) ) * cos( radians( Venue_Lat ) ) * cos( radians( Venue_Long ) - radians(#dmlLng) ) + sin( radians(#dmlLat) ) * sin( radians( Venue_Lat ) ) ) ) AS distance FROM Stores HAVING distance < #Radius ORDER BY distance LIMIT 0 , 20"
I'm trying to build a store locator for gas stations with google maps api.
I've done everything as described here (http://code.google.com/apis/maps/articles/phpsqlsearch.html), but
The search for address function does not recognize most of the input (I can live with that)
The SQL statement as provided by google does not return any results (I've checked that by substituting the statement with "SELECT * FORM markers", which works)
My DB table looks like
ID
NAME
ADDRESS
LAT
LNG
and the statement I'm having troubles with is:
$query = sprintf("SELECT name, address, lat, lng ( 6371 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance FROM markers HAVING distance < '%s' ORDER BY distance LIMIT 0 , 5",
mysql_real_escape_string($center_lat),
mysql_real_escape_string($center_lng),
mysql_real_escape_string($center_lat),
mysql_real_escape_string($radius));
$result = mysql_query($query);
which gets its values from the address search.
Does anybody have experience with this or a similar problem?
edit: found the first error: i missed out a comma between lng and (6371...
if I insert this directly in phpmyadmin (substituting '%s' with real values) i get the result i want, so I suppose the problem is passing the variables into SQL;
hope that helps narrowing it down.
You need to pass in floats instead of strings, so your php should be
$query = sprintf("SELECT name, address, lat, lng, ( 6371 * acos( cos( radians(%f) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(%f) ) + sin( radians(%f) ) * sin( radians( lat ) ) ) ) AS distance FROM markers HAVING distance < %d ORDER BY distance LIMIT 0 , 5",
mysql_real_escape_string($center_lat),
mysql_real_escape_string($center_lng),
mysql_real_escape_string($center_lat),
mysql_real_escape_string($radius));
$result = mysql_query($query);