Determining distances MySQL - mysql

My code is as follows and should work but for some reason it is not recognizing wm_stores.lat in the join statement. Anyone have any ideas?
SELECT wm_dcs.dc_id, wm_stores.store_id
FROM wm_dcs
JOIN wm_stores
ON wm_stores.lat BETWEEN wm_dcs.lat - (250.0 / 69.0)
AND wm_dcs.lat + (250.0 / 69.0)
AND wm_stores.lon BETWEEN wm_dcs.lon - (250.0 / (69.0 * COS(RADIANS(wm_dcs.lat))))
AND wm_dcs.lon + (250.0 / (69.0 * COS(RADIANS(wm_dcs.lat))))
AND (69.0 * DEGREES(ACOS(COS(RADIANS(wm_dcs.lat) * COS(RADIANS(stores.latitude))
* COS(RADIANS(dc.longitude - stores.longitude))
+ SIN(RADIANS(dc.latitude))
* SIN(RADIANS(wm_stores.lon)))))) <= 250.0;
Different Version of code:
set #dc_lat = 40.811973 ;
set #dc_lon = -73.946299 ;
select wm_stores.store_id,
( 3959 * acos( cos( radians(#dc_lat) ) * cos( radians(wm_stores.lat ) )
* cos( radians( wm_stores.lon ) - radians(#dc_lon) ) + sin( radians(#dc_lat) )
* sin( radians( wm_stores.lat ) ) ) ) AS distance
from wm_stores
having distance <= 250
order by distance asc;

In your query
SELECT wm_dcs.dc_id, wm_stores.store_id
FROM wm_dcs
JOIN wm_stores
ON wm_stores.lat BETWEEN wm_dcs.lat - (250.0 / 69.0)
AND wm_dcs.lat + (250.0 / 69.0)
AND wm_stores.lon BETWEEN wm_dcs.lon - (250.0 / (69.0 * COS(RADIANS(wm_dcs.lat))))
AND wm_dcs.lon + (250.0 / (69.0 * COS(RADIANS(wm_dcs.lat))))
AND (69.0 * DEGREES(ACOS(COS(RADIANS(wm_dcs.lat) * COS(RADIANS(stores.latitude))
* COS(RADIANS(dc.longitude - stores.longitude))
+ SIN(RADIANS(dc.latitude))
* SIN(RADIANS(wm_stores.lon)))))) <= 250.0;
I noticed there is no table like stores but you have used stores.latitude and stores.longitude in your query. May be this is causing the error message Unknown column 'stores.latitude' in 'on clause'.
I suggest you to re-examine the code
AND (69.0 * DEGREES(ACOS(COS(RADIANS(wm_dcs.lat) * COS(RADIANS(stores.latitude))
* COS(RADIANS(dc.longitude - stores.longitude))
+ SIN(RADIANS(dc.latitude))
* SIN(RADIANS(wm_stores.lon)))))) <= 250.0;

Related

The diffrence in mysql and psql syntax - finding the closest geocoordinates

I found a psql code which looks like this:
select * from (
SELECT *,( 3959 * acos( cos( radians(6.414478) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(12.466646) ) + sin( radians(6.414478) ) * sin( radians( lat ) ) ) ) AS distance
FROM station_location
) al
where distance < 5
ORDER BY distance
LIMIT 20;
find the nearest location by latitude and longitude in postgresql
The problem is I completely don't get it.
Before I used to use mysql and the syntax was completely different:
SELECT latitude, longitude, SQRT(
POW(69.1 * (latitude - [startlat]), 2) +
POW(69.1 * ([startlng] - longitude) * COS(latitude / 57.3), 2)) AS distance
FROM TableName HAVING distance < 25 ORDER BY distance;
Find nearest latitude/longitude with an SQL query
How to convert this mysql instruction into psql, so the user's longitude and latitude will be startlng and startlat?
Not commenting on the calculations themselves, this "port" to PostgreSQL should work:
select * from (select SQRT(
POW(69.1 * (10 - 8), 2) +
POW(69.1 * (100 - 10) * COS(10 / 57.3), 2)) AS distance
from table) d where distance < 25 ORDER BY distance;

Add more conditions to Haversine Formula in SQL query

Please I need help with adding one more condition to the below database query. I'm using Haversine Formula to get the 15 closest locations to my user's location. I have succeeded in doing this, however I wish to narrow the condition to only display the closest locations if serviceName equals a $serviceName in my query.
I wish to add WHERE serviceName="$serviceName";.
My Query:
$sql = "
SELECT uid, inCallPriceOneTime, lat, lng, distance
FROM
(
SELECT z.uid, z.inCallPriceOneTime, z.lat, z.lng,
p.radius, p.distance_unit *
DEGREES(ACOS(COS(RADIANS(p.latpoint)) *
COS(RADIANS(z.lat)) *
COS(RADIANS(p.longpoint - z.lng))
+ SIN(RADIANS(p.latpoint)) *
SIN(RADIANS(z.lat))))
AS distance
FROM selectedservice AS z
JOIN
(
SELECT $lat AS latpoint, $lng AS longpoint, 50.0 AS radius,
111.045 AS distance_unit
) AS p
WHERE z.lat
BETWEEN p.latpoint - (p.radius / p.distance_unit)
AND p.latpoint + (p.radius / p.distance_unit)
AND z.lng
BETWEEN p.longpoint - (p.radius / (p.distance_unit *
COS(RADIANS(p.latpoint))))
AND p.longpoint + (p.radius / (p.distance_unit *
COS(RADIANS(p.latpoint))))
) AS d
WHERE distance <= radius
ORDER BY distance LIMIT 15";
Any help will be greatly appreciated.
Thanks in advance.

Find time difference and distance between two Lat-Long pairs

I am trying to find the time difference ad distance between two lat long pairs.
I am getting incorrect values of time for a few records
SELECT A.ID, A.latitude, A.longitude, A.drive_time, (B.drive_time - A.drive_time) AS time_difference, 6367 * acos( cos(
radians(A.latitude) )
* cos( radians(B.latitude) )
* cos( radians(B.longitude) - radians(A.longitude)) + sin(radians(A.latitude))
* sin( radians(B.latitude) ) as distance
FROM mapper A INNER JOIN mapper B ON B.ID = (A.ID + 1);
Never mind I found my solution.
SELECT A.ID, A.latitude, A.longitude, B.drive_time, 6371000 * 2 * ASIN(SQRT(
POWER(SIN((A.latitude - abs(B.latitude)) * pi()/180 / 2),
2) + COS(A.latitude * pi()/180 ) * COS(abs(B.latitude) *
pi()/180) * POWER(SIN((A.longitude - B.longitude) *
pi()/180 / 2), 2) )) as distance ,time_to_sec(TIMEDIFF(B.drive_time,A.drive_time)) AS time_difference
FROM mapper A left JOIN mapper B ON B.ID = A.ID + 1

Zipcode Radius Search with POINT Column

I have a MySQL Routine that is getting records within a 50 mile radius when passed Latitude and Longitude via utilizing the Haversin equation.
While this works great, and is pretty speedy (considering it's searching through 82k records), I am thinking that I can get better performance by creating a similar procedure utilizing a POINT column.
So, in my table I created an extra column called Location, gave it a datatype of POINT, updated my data to pass lat & lon to the Location column. Data is valid, and is fine., and added a Spatial Index
The question is, how can I convert the following query to use the Location column, instead of lat and lon columns.
SET #LAT := '37.953';
SET #LON := '-105.688';
SELECT DISTINCT
BPZ.`store_id`,
3956 * 2 * ASIN(SQRT(POWER(SIN((#LAT - abs(Z.`lat`)) * pi()/180 / 2),2) + COS(#LAT * pi()/180 ) * COS(abs(Z.`lat`) * pi()/180) * POWER(SIN((#LON - Z.`lon`) * pi()/180 / 2), 2))) as distance,
c.`name`,c.`address`,c.`city`,c.`state`,c.`phone`,c.`zip`,c.`premise_type`
FROM
`zip_codes` as Z,
`brand_product_zip` as BPZ
LEFT JOIN `customers` c ON c.`store_id` = BPZ.`store_id`
WHERE
BPZ.`zip` = Z.`zip`
AND
3956 * 2 * ASIN(SQRT(POWER(SIN((#LAT - abs(Z.`lat`)) * pi()/180 / 2),2) + COS(#LAT * pi()/180 ) * COS(abs(Z.`lat`) * pi()/180) * POWER(SIN((#LON - Z.`lon`) * pi()/180 / 2), 2))) <= 50
ORDER BY
distance LIMIT 20
I understand that this has been asked before, however, everything I see points to calculations based on lat and lon and not the POINT column
Updated Code:
SET #lat = 41.92;
SET #lon = -72.65;
SET #kmRange = 80.4672; -- = 50 Miles
SELECT *, (3956 * 2 * ASIN(SQRT(POWER(SIN((#lat - abs(`lat`)) * pi()/180 / 2),2) + COS(#lat * pi()/180 ) * COS(abs(`lat`) * pi()/180) * POWER(SIN((lon - `lon`) * pi()/180 / 2), 2)))) as distance
FROM `zip_codes`
WHERE MBRContains(LineString(Point(#lat + #kmRange / 111.1, #lon + #kmRange / (111.1 / COS(RADIANS(#lat)))), Point(#lat - #kmRange / 111.1, #lon - #kmRange / (111.1 / COS(RADIANS(#lat))))), `Location`)
Order By distance
LIMIT 20
Have you looked into hilbert curves solutions? A spatial index doesn't deliver the exact solution? . With a mysql spatial index you can use mbrcontains:
CREATE TABLE lastcrawl (id INT NOT NULL PRIMARY KEY, pnt POINT NOT NULL) ENGINE=MyISAM;
INSERT
INTO lastcrawl
VALUES (1, POINT(40, -100));
SET #lat = 40;
SET #lon = -100;
SELECT *
FROM lastcrawl
WHERE MBRContains
(
LineString
(
Point
(
#lat + 10 / 111.1,
#lon + 10 / ( 111.1 / COS(RADIANS(#lat)))
),
Point (
#lat - 10 / 111.1,
#lon - 10 / ( 111.1 / COS(RADIANS(#lat)))
)
),
pnt
);
Look here: MySQL - selecting near a spatial point.
Here: http://www.drdobbs.com/database/space-filling-curves-in-geospatial-appli/184410998
The article Nearest-location finder for MySQL explains in detail various options, and the best choice for use with the Spatial Extensions starting with MySQL 5.6.
From the article, this sample query lists zip codes within a 50 mile radius from given coordinates (42.81, -70.81):
SELECT zip, primary_city,
latitude, longitude, distance_in_mi
FROM (
SELECT zip, primary_city, latitude, longitude,r,
69.0 * DEGREES(ACOS(COS(RADIANS(latpoint))
* COS(RADIANS(latitude))
* COS(RADIANS(longpoint) - RADIANS(longitude))
+ SIN(RADIANS(latpoint))
* SIN(RADIANS(latitude)))) AS distance_in_mi
FROM zip
JOIN (
SELECT 42.81 AS latpoint, -70.81 AS longpoint, 50.0 AS r
) AS p
WHERE latitude
BETWEEN latpoint - (r / 69)
AND latpoint + (r / 69)
AND longitude
BETWEEN longpoint - (r / (69 * COS(RADIANS(latpoint))))
AND longpoint + (r / (69 * COS(RADIANS(latpoint))))
) d
WHERE distance_in_mi <= r
ORDER BY distance_in_mi;

SQL query issue - Unknown column error

I'm trying to select db records based on wordpress custom fields that hold lat and long and have hit a brick wall on this query. Anyone see anything obvious that i'm overlooking?
Thanks!
WordPress database error: [Unknown column 'latitude.meta_value' in 'field list']
SELECT p.ID, p.post_title, (( ACOS( SIN( 39.1749 * PI() / 180 )
* SIN( `latitude.meta_value` * PI() / 180 )
+ COS( 39.1749 * PI() / 180 )
* COS( `latitude.meta_value` * PI() / 180 )
* COS(( -94.5804 - `longitude.meta_value` ) * PI() / 180 )) * 180 / PI() ) * 60 * 1.1515 ) AS distance
FROM wp_posts p
LEFT JOIN wp_postmeta latitude ON latitude.post_id = p.ID AND latitude.meta_key = 'neighborly_issue_lat'
LEFT JOIN wp_postmeta longitude ON longitude.post_id = p.ID AND longitude.meta_key = 'neighborly_issue_lng' HAVING distance < 10;
Yours commas are wrong, try with :
SELECT p.ID, p.post_title, (( ACOS( SIN( 39.1749 * PI() / 180 )
* SIN( `latitude`.`meta_value` * PI() / 180 )
+ COS( 39.1749 * PI() / 180 )
* COS( `latitude`.`meta_value` * PI() / 180 )
* COS(( -94.5804 - `longitude`.`meta_value` ) * PI() / 180 )) * 180 / PI() ) * 60 * 1.1515 ) AS distance