I'm trying to get * from the users2 table where the user's location is within the given radius.
The location query works fine on the user_location2 table.
SELECT uid, ( 3959 * acos( cos( radians(28.247800068217) ) * cos( radians( `lat` ) ) * cos( radians( `lon` ) - radians(-80.726205977101) )
+ sin( radians(28.247800068217) ) * sin( radians( `lat` ) ) ) )
AS distance FROM user_location2
HAVING distance <= 25 ORDER BY time_stamp
and the inner join works fine without the location subquery
SELECT *
FROM users2
LEFT JOIN user_location2
ON user_location2.uid = users2.id
I'm just having trouble combining the two. Here's my current query that just is returning all rows, so I'm obviously doing something wrong.
SELECT *
FROM users2
LEFT JOIN user_location2
ON user_location2.uid = users2.id
WHERE EXISTS (SELECT NULL, ( 3959 * acos( cos( radians(26.247800068217) ) * cos( radians( `lat` ) ) * cos( radians( `lon` ) - radians(-89.726205977101) ) + sin( radians(26.247800068217) ) * sin( radians( `lat` ) ) ) )
AS distance FROM user_location2
HAVING distance <= 5 ORDER BY time_stamp)
Edit included
I'm hoping to add in a 3rd table (user_like) to eliminate a lot of possible rows that shouldn't be included in the result.
Let's say the script is running for user_id = 88
So basically users 89, 90 and 91 would fall under the location radius, but wouldn't be included in the result because user 88 already liked them.
Try this...
SELECT users2.*
FROM users2
LEFT JOIN user_location2
ON user_location2.uid = users2.id
WHERE ( 3959 * acos( cos( radians(28.247800068217) ) * cos( radians( `lat` ) ) * cos( radians( `lon` ) - radians(-80.726205977101) )
+ sin( radians(28.247800068217) ) * sin( radians( `lat` ) ) ) ) < = 5
ORDER BY time_stamp
The join is fine between the two tables. The calculated column has been added in the select clause and the where clause because the filter requires it there. It would be easier to put that through a view so that if you need to change it, it can be done in one place.
EDIT: Removed the calculation from SELECT because I believe you don't need to see that. Just left it in the WHERE clause since it needs to be filtered on.
You can try this :
SELECT *
FROM users2 A
LEFT JOIN user_location2 B
ON B.uid = A.id
WHERE ( 3959 * acos( cos( radians(26.247800068217) ) * cos( radians( `B.lat` ) ) * cos( radians( `B.lon` ) - radians(-89.726205977101) ) + sin( radians(26.247800068217) ) * sin( radians( `B.lat` ) ) ) ) > 25;
Related
I have created a filter where users can find locations within a selected number of miles of a specific point,
My code is the following, I keep getting SQL syntax error near the "left join"
Not sure what the error is, if anyone could help that would be ace, or just point me in the right direction!
SELECT b.*, host,
(6371 *
acos(
cos( radians( '51.514294' ) ) *
cos( radians( `latitude` ) ) *
cos(
radians( `longitude` ) - radians( '-0.042857' )
) +
sin(radians('51.514294')) *
sin(radians(`latitude`))
)
) `distance`
FROM brunches b HAVING
`distance` < $range
LEFT JOIN hosts ON hosts.id = b.hostid
You have an having clause in wrong place (the having clause must not placed between from and join)
SELECT b.*, host,
(6371 *
acos(
cos( radians( '51.514294' ) ) *
cos( radians( `latitude` ) ) *
cos(
radians( `longitude` ) - radians( '-0.042857' )
) +
sin(radians('51.514294')) *
sin(radians(`latitude`))
)
) `distance`
FROM brunches b
LEFT JOIN hosts ON hosts.id = b.hostid
HAVING `distance` < $range
I have a database that I keep lat, lng, so find solution to select routes in radius using this code
SELECT `id`, (3959 * acos( cos( radians(46.352165) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(6.096681) ) + sin( radians(46.352165) ) * sin(radians(lat)) ) )
AS distance FROM`routes` HAVING distance < 1`
But now can't find solution to update one of the columns with the results of select I use.
If you want to update routes :
UPDATE routes JOIN
(
SELECT `id`, (3959 * acos( cos( radians(46.352165) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(6.096681) ) + sin( radians(46.352165) ) * sin(radians(lat)) ) ) as distance from routes having distance <1
) as t2
ON (routes.id = t2.id)
SET varYouWantToSet=distance;
Your question confuse me a little, so forgive me if I am not answering correctly ^^'
UPDATE routes
INNER JOIN
(
SELECT `id`, (3959 * acos( cos( radians(46.352165) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(6.096681) ) + sin( radians(46.352165) ) * sin(radians(lat)) ) ) AS YOURUPDATEDVAL from routes having distance <1
) Z
ON (routes.id = Z.id)
SET routes.YOURUPDATECOLUMN=Z.YOURUPDATEDVAL;
As mention in above query ,you can try inner join which will made by Some sample table here it is Z.
And now you can update your column value using that value return by inner table or query.
Here i had mention that using SET routes.YOURUPDATECOLUMN=Z.YOURUPDATEDVAL.
Hope this will helps you.
I'm trying to display advertisements relevant to data of the user.
Here, data is Latitude and longitude.
ADS table: ad to display with ad name, ad text, latitude and longitude
Tables with data of the user:
TABLE1: user id + latitude and longitude,
TABLE2: user id + latitude and longitude,
TABLE3: user id + latitude and longitude,
TABLE4: user id + latitude and longitude
The purpose is to display an ad, when the latitude and longitude of the ad matches the latitude and longtitude of one or more lines in the 4 tables in a range of 10km and limit by 3 results.
It's working when linking one ad with one table in range of 10km, but doesn't with more tables.
- I'm not comfortable with OUTER JOINS -
My query looks like this and I'm pretty sure I'm going wrong...
SELECT ADS.name, ADS.text,
( 6371 * acos( cos( radians(TABLE1.latitude) )
* cos( radians( ADS.latitude ) )
* cos( radians( ADS.longitude )
- radians(TABLE1.longitude) )
+ sin( radians(TABLE1.latitude) )
* sin( radians( ADS.latitude ) ) ) )
AS check1,
( 6371 * acos( cos( radians(TABLE2.latitude) )
* cos( radians( ADS.latitude ) )
* cos( radians( ADS.longitude )
- radians(TABLE2.longitude) )
+ sin( radians(TABLE2.latitude) )
* sin( radians( ADS.latitude ) ) ) )
AS check2,
( 6371 * acos( cos( radians(TABLE3.latitude) )
* cos( radians( ADS.latitude ) )
* cos( radians( ADS.longitude )
- radians(TABLE3.longitude) )
+ sin( radians(TABLE3.latitude) )
* sin( radians( ADS.latitude ) ) ) )
AS check3,
( 6371 * acos( cos( radians(TABLE4.latitude) )
* cos( radians( ADS.latitude ) )
* cos( radians( ADS.longitude )
- radians(TABLE4.longitude) )
+ sin( radians(TABLE4.latitude) )
* sin( radians( ADS.latitude ) ) ) )
AS check4
FROM ADS
RIGHT OUTER JOIN TABLE1
ON TABLE1.user = ?
RIGHT OUTER JOIN TABLE2
ON TABLE2.user = ?
RIGHT OUTER JOIN TABLE3
ON TABLE3.user = ?
RIGHT OUTER JOIN TABLE4
ON TABLE4.user = ?
HAVING check1 < 10 OR check2 < 10 OR check3 < 10 OR check4 < 10
LIMIT 0,3
If user isn't unique in TABLE1 (or any of the TABLEn), then there's a potential to return multiple copies of the same row from ADS.
With the query the way it is, if the specified user isn't found in TABLE4, then the query won't return any rows. I suspect what you meant was a LEFT JOIN, with ADS as the driving table, but that's just a guess. We don't know what those tables contain, why are there four of them, etc.)
If there's a reason you are using a RIGHT JOIN, and if the query with one table is working for you...
and if there is a small number of rows in each of TABLE1, TABLE2, TABLE3, TABLE4 for a specified user...
You could concatenate the results of queries of those tables into single derived table, and then join to the derived table. As an example:
SELECT ADS.name, ADS.text,
( 6371 * acos( cos( radians(t.latitude) )
* cos( radians( ADS.latitude ) )
* cos( radians( ADS.longitude )
- radians(t.longitude) )
+ sin( radians(t.latitude) )
* sin( radians( ADS.latitude ) ) )
) AS check1
FROM ADS
RIGHT
JOIN ( SELECT TABLE1.latitude, TABLE1.longitude
FROM TABLE1 WHERE TABLE1.user = ?
UNION ALL
SELECT TABLE2.latitude, TABLE2.longitude
FROM TABLE2 WHERE TABLE2.user = ?
UNION ALL
SELECT TABLE3.latitude, TABLE3.longitude
FROM TABLE3 WHERE TABLE3.user = ?
UNION ALL
SELECT TABLE4.latitude, TABLE4.longitude
FROM TABLE4 WHERE TABLE4.user = ?
) t
HAVING check1 < 10
LIMIT 3
This was finaly what I needed:
$reponse = $bdd->prepare('
SELECT * FROM
(
SELECT ADS.id AS id, ADS.name, ADS.text,
( 6371 * acos( cos( radians(t.latitude) )
* cos( radians(ADS.latitude ) )
* cos( radians( ADS.longitude )
- radians(t.longitude) )
+ sin( radians(t.latitude) )
* sin( radians( ADS.latitude ) ) ) )
AS distance
FROM ADS
RIGHT
JOIN ( SELECT TABLE1.latitude, TABLE1.longitude
FROM TABLE1 WHERE TABLE1.user = :user
UNION ALL
SELECT TABLE2.latitude, TABLE2.longitude
FROM TABLE2 WHERE TABLE2.user = :user
UNION ALL
SELECT TABLE3.latitude, TABLE3.longitude
FROM TABLE3 WHERE TABLE3.user = :user
UNION ALL
SELECT TABLE4.latitude, TABLE4.longitude
FROM TABLE4 WHERE TABLE4.user = :user
) t
ON 1
HAVING distance < 10
) req GROUP BY id LIMIT 0,3
');
$reponse->execute(array('user' => $_SESSION['id']));
I know this is a replica of some question asked already, but i need some suggestion.
I know basics of MySQL, i have a query to calculate distance between latitude and longitude and based on minimum distance i am returning id's.
now i don't want the distance column as result of my query. How to do it.
Here is my query.
select cl.wp_id,( 3959 * acos( cos( radians(12.91841) ) * cos( radians( y(gproperty) ) ) *
cos( radians( x(gproperty)) - radians(77.58631) ) + sin( radians(12.91841) ) *
sin( radians(y(gproperty) ) ) ) ) AS distance
from db1.geofeature gf, db2.c_loc cl where gf.o_type = 10 and cl.c_info_id = 23
and gf.o_id = cl.wp_id
having distance < 10 order by distance limit 10;
i want only my cl.wp to be displayed as result. How to do that.?
EDIT
now i have 3 tables how to join them.?
select dlo.id,( 3959 * acos( cos( radians(12.9) ) * cos( radians( y(gproperty) ) ) * cos( radians( x(gproperty)) - radians(77.5) ) +sin( radians(12.9) ) * sin( radians(y(gproperty) ) ) ) ) AS distance from db1.gfeature dgf, db2.loc dlo, db2.cust dcu where gf.o_type = 6 and dcu.id = 240 and dgf.o_id = dlo.p_id having distance < 20 order by distance limit 10;
Any suggestions are welcome.
You would want to use a subquery:
select wp_id
from (select cl.wp_id,( 3959 * acos( cos( radians(12.91841) ) * cos( radians( y(gproperty) ) ) *
cos( radians( x(gproperty)) - radians(77.58631) ) + sin( radians(12.91841) ) *
sin( radians(y(gproperty) ) ) ) ) AS distance
from db1.geofeature gf join
db2.c_loc cl
on gf.o_type = 256 and cl.c_info_id = 146 and gf.o_id = cl.wp_id
) t
where distance < 10
order by distance
limit 10;
Notice that I also fixed the join syntax to use explicit joins.
I have two sql queries which when run independent produces the correct results
Query 1
SELECT id,
(6371 * acos( cos( radians(9.977364864079215) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.58620953448485) ) + sin( radians(9.977364864079215) ) * sin( radians( latitude ) ) ) )
AS distance
FROM geodata HAVING distance < 20
ORDER BY distance
LIMIT 0 , 20;
Query 2
SELECT DISTINCT e.* FROM schools e
WHERE (
(e.type = 'preprimary')
)
AND(
e.title LIKE '%government%'
)
LIMIT 0, 10
I want to merge the first query with the second one, so that it should return all "preprimary" type schools with title like "government" located within 20KM radius and the result needs to be ordered by the distance.
How can I merge the two queries? I tried using JOINING the geodata table on the school table. But I dont know the remaining. Sorry, if this is a silly question. I am pretty new to SQL world.
SELECT DISTINCT school.* FROM
( SELECT geodata.id,
(6371 * acos( cos( radians(9.977364864079215) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.58620953448485) ) + sin( radians(9.977364864079215) ) * sin( radians( latitude ) ) ) )
AS distance ,school.*
FROM geodata LEFT JOIN school on geodata.id=school.id
WHERE
(school.type = 'preprimary')
AND(
school.title LIKE '%government%'
)
AND school.id IS NOT NULL
HAVING distance < 20 )x
ORDER BY x.distance
LIMIT 0 , 10;
Try this:
SELECT *
From (
SELECT DISTINCT e.* ,
(6371 * acos( cos( radians(9.977364864079215) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(76.58620953448485) ) + sin( radians(9.977364864079215) ) * sin( radians( latitude ) ) )
) as distance
FROM schools e
LEFT JOIN geodata g ON e.id=g.id
WHERE (e.type = 'preprimary')
AND ( e.title LIKE '%government%' )
) as s
Where s.distance < 20
Order by s.distance