First -- I have read about 7 pages of posts with similar titles but couldn't find the right insight for my challenge
My SQL:
SELECT name, address, lat, lng, city, state, phone, zip, info
, ( 3959 * acos( cos( radians('37.4969') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('-122.2674') ) + sin( radians('37.4969') ) * sin( radians( lat ) ) ) ) AS distance
FROM myhealthfinder_map
HAVING distance < '50' and location = '2'
ORDER BY distance LIMIT 0 , 10
I get the error message: Invalid query: Unknown column 'location' in 'having clause'
if instead of HAVING I just make it WHERE location = '2' then it works fine [it finds the column] (but I need the distance selector).
Any suggestion on how to knock this down?
Use both WHERE and HAVING. HAVING is used for aggregated and calculated columns. And WHERE on plain old columns.
SELECT name, address, lat, lng, city, state, phone, zip, info
, ( 3959 * acos( cos( radians('37.4969') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('-122.2674') ) + sin( radians('37.4969') ) * sin( radians( lat ) ) ) ) AS distance
FROM myhealthfinder_map
WHERE location = '2'
HAVING distance < '50'
ORDER BY distance LIMIT 0 , 10
More explanation found here WHERE vs HAVING
Don't use HAVING without GROUP BY. You can try this instead
SELECT name, address, lat, lng, city, state, phone, zip, info, ( 3959 * acos( cos( radians('37.4969') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('-122.2674') ) + sin( radians('37.4969') ) * sin( radians( lat ) ) ) ) AS distance
FROM myhealthfinder_map
WHERE location = '2' AND
( 3959 * acos( cos( radians('37.4969') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('-122.2674') ) + sin( radians('37.4969') ) * sin( radians( lat ) ) ) ) < 50
ORDER BY distance LIMIT 0 , 10
It's not pretty, but it should work.
Related
I have a table which has some users in it. They all have a username, latitude,longitude and some other fields.
I want to select all users within 5KM range of a given coordinate and based on some other criteria. Now this part was not hard.
However, I also want the SQL statement to return users with given usernames independently from the other criterias mentioned above.
So, basically, the SQL should return users based on the distance and other criterias AND users who have a specific username despite if they match the criterias or no.
Here is what I have, but it does not work:
SELECT idUser
, username
, telephone
, latitude
, longitude
, ( 6371 * acos( cos( radians(?) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(?) ) + sin( radians(?) ) * sin( radians( latitude ) ) ) ) AS distance
FROM main
WHERE active = ?
AND idUser != ?
HAVING distance < 5
OR username = mike
OR username = john
You can add the condition to the having clause:
SELECT idUser, username, telephone, latitude, longitude,
( 6371 * acos( cos( radians(?) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(?) ) + sin( radians(?) ) * sin( radians( latitude ) ) ) ) AS distance
FROM main
WHERE active = ? AND idUser != ?
HAVING distance < 5 OR username IN ('mike', 'john');
You may need to remove the idUser . . . I'm not sure if that is related to username or not.
EDIT:
If you want to guarantee that mike and john are in the result set, you can do:
(SELECT idUser, username, telephone, latitude, longitude,
( 6371 * acos( cos( radians(?) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(?) ) + sin( radians(?) ) * sin( radians( latitude ) ) ) ) AS distance
FROM main
WHERE active = ? AND idUser != ? AND username NOT IN ('mike', 'john')
HAVING distance < 5
)
UNION ALL
(SELECT idUser, username, telephone, latitude, longitude,
( 6371 * acos( cos( radians(?) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(?) ) + sin( radians(?) ) * sin( radians( latitude ) ) ) ) AS distance
FROM main
WHERE username IN ('mike', 'john')
)
Or:
SELECT idUser, username, telephone, latitude, longitude,
( 6371 * acos( cos( radians(?) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(?) ) + sin( radians(?) ) * sin( radians( latitude ) ) ) ) AS distance
FROM main
WHERE (active = ? AND idUser <> ?) OR username IN ('mike', 'john')
HAVING distance < 5 OR username IN ('mike', 'john');
Or move all conditions to the HAVING clause:
SELECT idUser, username, telephone, latitude, longitude,
( 6371 * acos( cos( radians(?) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(?) ) + sin( radians(?) ) * sin( radians( latitude ) ) ) ) AS distance
FROM main
WHERE (active = ? AND idUser <> ?) OR username IN ('mike', 'john')
HAVING (active = ? AND idUser <> ? AND distance < 5) OR
username IN ('mike', 'john');
SELECT
id,
( 3959 * acos( cos( radians(51.509980) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-0.133700 ) ) + sin( radians(51.509980) ) * sin(radians(lat)) ) ) AS distance
FROM tbl_event
HAVING distance < 5
ORDER BY distance
Here -0.133700 is creating problem, other minus values like -122 etc. are working fine with this.
Please help if anyone is aware of this issue.
It returns null because acos function get an argument greater than 1 or lower than -1. Try this :
Select id, 3959 * acos(if(d>1, 1, if(d<-1, -1, d))) as distance
From (SELECT id,
cos( radians(51.509980) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-0.133700 ) ) + sin( radians(51.509980) ) * sin(radians(lat)) AS d
FROM tbl_event ) t1
HAVING distance < 5
ORDER BY distance
Making a dealer locator where people search for a dealer near them. I want it to work in such a way that if a dealer has multiple branches near the person, only the closest branch shows. So the "name" field should be unique in the results with the result shown having the least distance to the person searching versus other rows that have the same "name" field. I also want only the closest 5 dealers shown ordered by their dealer level, or medal. Right now I have the following:
$query = sprintf("SELECT
name, address, contact, image, medal, phone, email, website, lat, lng,
( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance
FROM dealers
HAVING distance < 60
ORDER BY medal, 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);
From what I've read, it sounds like I need to do something like:
SELECT * FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY name ORDER BY distance) AS num
FROM dealers)a
WHERE a.num = 1
Or something like that, but I can't get it to work right. Any insights on how I can get this to function would be greatly appreciated.
Get the minimum distance per dealer and of these take the first five. Then select again from the table in order to get complete records, but take only those records already identified by dealer and distance.
A WITH clause would be helpful, but MySQL doesn't support it. Well, ...
SELECT
name, address, contact, image, medal, phone, email, website, lat, lng,
( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance
FROM dealers
WHERE (name, ( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) )) IN
(
SELECT
name, min( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance
FROM dealers
GROUP BY name
HAVING distance < 60
ORDER BY distance
LIMIT 5
)
ORDER BY distance, medal;
Final Solution was:
SELECT name, address, contact, image, medal, phone, email, website, lat, lng,
( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance
FROM dealers
WHERE (name,
( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) )
IN
(SELECT name, distance
FROM (SELECT name,
MIN( 3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) AS distance
FROM dealers
WHERE (3959 * acos( cos( radians('%s') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('%s') ) + sin( radians('%s') ) * sin( radians( lat ) ) ) ) < 90
GROUP BY name)
t)
ORDER BY medal, 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($center_lat),
mysql_real_escape_string($center_lng),
mysql_real_escape_string($center_lat),
mysql_real_escape_string($center_lat),
mysql_real_escape_string($center_lng),
mysql_real_escape_string($center_lat),
mysql_real_escape_string($center_lat),
mysql_real_escape_string($center_lng),
mysql_real_escape_string($center_lat)
Thank you Thorsten Kettner, for putting me on the right track!
I am using the MySQL query to find distance between tow zip-codes when lat long is given.
SELECT postcode, ( 3959 * acos( cos( radians( 52.47592 ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians( -1.90539 ) ) + sin( radians( 52.47592 ) ) * sin( radians( latitude ) ) ) ) AS distance FROM ukpostcodes HAVING distance <= 5 ORDER BY distance
it is working fine. But I want only postcode in result. I don't want distance column in result .
How can I achieve it.
Thanks
SELECT postcode FROM(
SELECT postcode, ( 3959 * acos( cos( radians( 52.47592 ) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians( -1.90539 ) ) + sin( radians( 52.47592 ) ) * sin( radians( latitude ) ) ) ) AS distance FROM ukpostcodes HAVING distance <= 5 ORDER BY distance
) AS tbl
First part of the query:
SET #centerLat = '48.531157';
SET #centerLng = '-123.782959';
SELECT user_id, lat, lng, ( 3959 * acos( cos( radians( #centerLat ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(#centerLng) ) + sin( radians( #centerLat ) ) * sin( radians( lat ) ) ) ) AS distance FROM bid_userloc HAVING distance < 25 ORDER BY distance LIMIT 0 , 20
Second aspect is taking the user_id and grabbing a bunch of information from the USERS table
I'm still learning what JOIN even means and I don't quite understand how it all works best...
you may try this
SELECT user_id, lat, lng, ( 3959 * acos( cos( radians( #centerLat ) )
* cos( radians( lat ) ) * cos( radians( lng ) - radians(#centerLng) )
+ sin( radians( #centerLat ) ) * sin( radians( lat ) ) ) )
AS distance,columnsfromuserstable FROM bid_userloc bid
inner join users us on bid.user_id=us.user_id
HAVING distance < 25
ORDER BY distance LIMIT 0 , 20
You can try something like this:
select * from users where user_id in (select user_id from(
SELECT user_id, lat, lng, ( 3959 * acos( cos( radians( #centerLat ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(#centerLng) ) + sin( radians( #centerLat ) ) * sin( radians( lat ) ) ) ) AS distance FROM bid_userloc HAVING distance < 25 ORDER BY distance LIMIT 0 , 20
));
Variant with JOIN -
SET #centerLat = '48.531157';
SET #centerLng = '-123.782959';
SELECT
t1.user_id, t1.lat, t1.lng,
(3959 * ACOS(COS(RADIANS(#centerLat)) * COS(RADIANS(t1.lat)) * COS(RADIANS(t1.lng) - RADIANS(#centerLng)) + SIN(RADIANS(#centerLat)) * SIN(RADIANS(t1.lat)))) distance,
t2.*
FROM
bid_userloc t1
JOIN users t2
ON t1.user_id = t2.user_id
HAVING
distance < 25
ORDER BY
distance
LIMIT
0, 20;