# find locations near zip code

Hi,

We have an intranet application that looks up our retail locations based on the customers zip code (so we can direct them to the nearest store). It's actually an MS SQL stored procedure.

We want to port this to a MySQL/PHP application. Here is the stored procedure that determines the nearest locations:

------------------------------------------------------
CREATE Procedure sp_RetailerDistance

(
@pLAT float,
@pLNG float
)

As
SELECT TOP 20
ARX_RetailerLocatorList.CustomerNumber,
ARX_RetailerLocatorList.ShipToCode,
ARX_RetailerLocatorList.CustomerName,
ARX_RetailerLocatorList.City,
ARX_RetailerLocatorList.State,
ARX_RetailerLocatorList.ZipCode,
ARX_RetailerLocatorList.PhoneNumber,
ZipLocation.LAT,
ZipLocation.LNG,
STR(3959 * acos(sin(LAT/57.3)*sin(@pLAT/57.3) + cos(LAT/57.3) * cos(@pLAT/57.3) * cos(@pLNG/57.3 - LNG/57.3)),7,1) As Distance
FROM
dbo.ARX_RetailerLocatorList
INNER JOIN
dbo.ZipLocation
ON
LEFT(dbo.ARX_RetailerLocatorList.ZipCode, 5) = dbo.ZipLocation.ZIP_CODE
ORDER BY
Distance ASC

return
GO
----------------------------------------------------

I guess @pLAT and @pLNG are passed in as parameters? IF so, then I should figure out how those values are determined first... Basically I would like suggestions or a solution on how to port this to mysql. Maybe there's already a solution out there that does something similar. I would rather not do it as a stored procedure (and would prefer a php-based solution), but whatever works is good for me...

Thanks!
###### Who is Participating?

Commented:
The calcualtions you do will have invalid results according to the calculations shown here: http://mathforum.org/library/drmath/view/51711.html

The stored procedure shold be rewritten like this:

STORED PROCEDURE:
==================

CREATE Procedure sp_RetailerDistance

(
@pLAT float,
@pLNG float
)

As
SELECT TOP 20
ARX_RetailerLocatorList.CustomerNumber,
ARX_RetailerLocatorList.ShipToCode,
ARX_RetailerLocatorList.CustomerName,
ARX_RetailerLocatorList.City,
ARX_RetailerLocatorList.State,
ARX_RetailerLocatorList.ZipCode,
ARX_RetailerLocatorList.PhoneNumber,
ZipLocation.LAT,
ZipLocation.LNG,
CASE
WHEN (LAT = @pLAT AND LNG = @pLNG) THEN 0
WHEN ((SIN(LAT / 57.29577951) * SIN(@pLAT / 57.29577951)) + (COS(LAT / 57.29577951) * COS(@pLAT / 57.29577951) * COS((LNG / 57.29577951) - (@pLNG /57.29577951))) > 1) THEN STR(3963.1 * ACOS(1), 7, 1)
ELSE STR(3963.1 * ACOS(SIN(LAT / 57.29577951) * SIN(@pLAT / 57.29577951)) + (COS(LAT / 57.29577951) * COS(@pLAT / 57.29577951) * COS((LNG / 57.29577951) - (@pLNG /57.29577951))), 7, 1)
END AS Distance
FROM
dbo.ARX_RetailerLocatorList
INNER JOIN
dbo.ZipLocation
ON
LEFT(dbo.ARX_RetailerLocatorList.ZipCode, 5) = dbo.ZipLocation.ZIP_CODE
ORDER BY
Distance ASC

return
GO

And the PHP function can be something like this:

function RetailerDistance(\$pLAT, \$pLNG)
{
\$SQL = 'SELECT
ARX_RetailerLocatorList.CustomerNumber,
ARX_RetailerLocatorList.ShipToCode,
ARX_RetailerLocatorList.CustomerName,
ARX_RetailerLocatorList.City,
ARX_RetailerLocatorList.State,
ARX_RetailerLocatorList.ZipCode,
ARX_RetailerLocatorList.PhoneNumber,
ZipLocation.LAT,
ZipLocation.LNG,
CASE
WHEN (LAT = ' . \$pLAT . ' AND LNG = ' . \$pLNG . ') THEN 0
WHEN ((SIN(LAT / 57.29577951) * SIN(' . \$pLAT . ' / 57.29577951)) + (COS(LAT / 57.29577951) * COS(' . \$pLAT . ' / 57.29577951) * COS((LNG / 57.29577951) - (' . \$pLNG . ' /57.29577951))) > 1) THEN TRUNCATE(3963.1 * ACOS(1), 1)
ELSE TRUNCATE(3963.1 * ACOS(SIN(LAT / 57.29577951) * SIN(' . \$pLAT . ' / 57.29577951)) + (COS(LAT / 57.29577951) * COS(' . \$pLAT . ' / 57.29577951) * COS((LNG / 57.29577951) - (' . \$pLNG . ' /57.29577951))), 1)
END AS Distance
FROM
ARX_RetailerLocatorList
INNER JOIN
ZipLocation
ON (LEFT(ARX_RetailerLocatorList.ZipCode, 5) = ZipLocation.ZIP_CODE)
ORDER BY
Distance ASC
LIMIT 0, 20';

//
// EXECUTE THE SQL AND RETURN ITS RESULT
//
}

If you still want to work with the same calculations you use, It will be easy for you now to edit the SQL query.

Kind Regards
Bakr
0

Author Commented:
I've determined there's a "ziplocation" table that has the following columns:

zip, city, state, lng, lat

So the script first gets the lng and lat based on the zip provided. Then it passes those to the stored procedure.
0

IT/ProgrammingCommented:
The stored procedure does take the Latitude and Logitude from the other table as parameters.
You can write this as a PHP function relatively easily.  The first part would be to get the data into an equivilantly structured MySQL tables.

The newest versions of MySQL server allow for stored procedures as well so this could be ported directly into the MySQL server as a stored procedure.
0

Author Commented:
Right, but stored procedure syntax is different amongst various db's right? This is MS SQL SERVER:

STR(3959 * acos(sin(LAT/57.3)*sin(@pLAT/57.3) + cos(LAT/57.3) * cos(@pLAT/57.3) * cos(@pLNG/57.3 - LNG/57.3)),7,1) As Distance

Would that work directly in MYSQL?
0

IT/ProgrammingCommented:
MySQL does have mathematical functions for COS, aCOS, and SIN so it should work with minimal changes.
The function may need some tweaking if there is a sign order difference - but it doesn't look like it.
These functions have been available since at lease MySQL 4.0.3.
0

Commented:
Thanks for the A ;) Glad to hear that your problem has been solved.

Kind Regards
Bakr
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.