use join in distance searching and mysql - mysql

In mysql I am calculating all the points between two zip codes and that's working fine for me. Now I want update that query to join an additional table, but I am getting an error. Here is the query please have a look:
SELECT *
FROM users
INNER JOIN
(SELECT *,
ACOS(
COS(RADIANS(30.7261629))
* COS(RADIANS(lat_collection))
* COS(RADIANS(76.7596221) - RADIANS(`long_collection`))
+ SIN(RADIANS(30.7261629))
* SIN(RADIANS(lat_collection))
) * 3956 AS `distance`
FROM quote q
WHERE lat_collection BETWEEN 30.7261629 - (30 / 69) AND 30.3345816 + (30 / 69)
AND `long_collection` BETWEEN 76.7596221 - (30 / (69 * COS(RADIANS(30.7261629)))) AND 78.0537813 + (30 / (69* COS(RADIANS(30.7261629))))
) AS u
ON q.user_id=u.id
WHERE `distance` < 30
I need to join four-five table in the same query; how can I do that? I am getting an error when trying to join the tables (I have two zip codes and then I calculate lat long for both the zip codes).

You are using an alias in where condition .. this is not allowed you must reuse the full code instead of alias
SELECT *
FROM users inner join (
SELECT *, 3956 * ACOS(COS(RADIANS(30.7261629)) * COS(RADIANS(lat_collection)) * COS(RADIANS(76.7596221) -
RADIANS(`long_collection`))
+ SIN(RADIANS(30.7261629)) * SIN(RADIANS(lat_collection))) AS `distance`
FROM quote q
WHERE lat_collection BETWEEN 30.7261629 - (30 / 69) AND 30.3345816 + (30 / 69)
AND `long_collection` BETWEEN 76.7596221 - (30 / (69 * COS(RADIANS(30.7261629)))) AND 78.0537813 + (30 / (69* COS(RADIANS(30.7261629))))
) as u on users.id=u.user_id
WHERE (3956 * ACOS(COS(RADIANS(30.7261629)) * COS(RADIANS(lat_collection)) * COS(RADIANS(76.7596221) - RADIANS(`long_collection`))
+ SIN(RADIANS(30.7261629)) * SIN(RADIANS(lat_collection)))) < 30

Related

How to reuse variable from SQL SELECT statement in WHERE clause

I need to take out values from database , based on distance from any given point and then order by distance ascending. Longitude and latitudes are saved in database as float field. Here is my query
SELECT
*,
#distance : = 6371 * 2 * asin(sqrt(POW(sin(({lat} - radians(address.latitude)) / 2), 2) + cos({lat}) * cos(radians(address.latitude)) * POW(sin(({lon} - radians(address.longitude)) / 2), 2)))
FROM
service,
provider,
address
WHERE
service.provider_id = provider.id
AND provider.address_id = address.id
AND provider.status = True
AND
(
6371 * 2 * asin(sqrt(POW(sin(({lat} - radians(address.latitude)) / 2), 2) + cos({lat}) * cos(radians(address.latitude)) * POW(sin(({lon} - radians(address.longitude)) / 2), 2)))
)
< 10
order by
#distance
I need to reuse the distance for condition like where #distance < 10
but I'm unable to reuse, it returns empty list. whereas #distance in ORDER BY is working fine. How can i reuse variable in where clause ?
Assuming you do not need #DISTANCE outside the select, here's an approach to try:
SELECT *,
6371 * 2 * asin(sqrt(POW(sin(({lat} - radians(address.latitude)) / 2), 2) + cos({lat}) * cos(radians(address.latitude)) * POW(sin(({lon} - radians(address.longitude)) / 2), 2))) AS DISTANCE
FROM service,
provider,
address
WHERE
service.provider_id = provider.id
AND provider.address_id = address.id
AND provider.status = True
HAVING
DISTANCE < 10
ORDER BY
DISTANCE
Note that a I have given the calculation an alias DISTANCE(see far right of select) and used HAVING rather than WHERE for the reference to the alias.
Avoid using MySQL variables; they are obsolete in newer versions of MySQL. Also, it's better to use modern syntax join (SQL-92) instead of old joins.
Anyway, I think the following query produces what you want:
select *
from (
SELECT
*,
6371 * 2 * asin(sqrt(POW(sin(({lat} - radians(a.latitude)) / 2), 2)
+ cos({lat}) * cos(radians(a.latitude)) * POW(sin(({lon}
- radians(a.longitude)) / 2), 2))) as distance
FROM service s
JOIN provider p ON s.provider_id = p.id
JOIN address a ON p.address_id = a.id
WHERE p.status = True
) x
WHERE distance < 10
ORDER BY distance

Combining SQL Google Search with own SQL query

I am pretty new to SQL queries.
I have a google SQL Search example
SELECT cID,
(6371 * acos
(
cos(radians(51.455643))
* cos(radians(latCord))
* cos(radians(longCord) - radians(7.011555))
+ sin(radians(51.455643))
* sin(radians(latCord))
)
) AS distance
FROM breitengrade
HAVING distance < 50
ORDER BY distance
LIMIT 0, 20
and a own SQL query
SELECT breitengrade.cID
,breitengrade.latCord
,breitengrade.longCord
,Pages.cIsActive
FROM breitengrade
INNER JOIN Pages ON breitengrade.cID = Pages.cID
WHERE cIsActive = '1'
How can I combine these 2 queries into one so that I can get one single result set?
SELECT breitengrade.cID,
breitengrade.latCord,
breitengrade.longCord,
Pages.cIsActive
(6371 * acos
(
cos(radians(51.455643))
* cos(radians(latCord))
* cos(radians(longCord) - radians(7.011555))
+ sin(radians(51.455643))
* sin(radians(latCord))
)
) AS distance
FROM breitengrade
INNER JOIN Pages ON breitengrade.cID = Pages.cID
WHERE cIsActive = '1'
HAVING distance < 50
ORDER BY distance
LIMIT 0, 20

How to search for events in 5 km radius

I'm trying to select events in a 5 km radius and order them by likes and from oldest to newest. I know how to select events and order them by likes, but I can't figure this one out. The problem maybe is that the location is stored in a different table.
Database structure:
event plusone (like) location
id_event id_plusone id_location
location_id event_id lat
... user_id lon
... city_id
full_name
....
The SQL statement I'm trying:
SELECT 3956 * 2 * ASIN(
SQRT(POWER(SIN((50.127946 - abs(l.lat)) * pi()/180 / 2),2) + COS(50.127946 * pi()/180 ) *
COS(abs(l.lat) * pi()/180) * POWER(SIN((14.4882912 - l.lon) * pi()/180 / 2), 2) )) AS distance,e.*,COUNT( p.id_plusone ) AS
likes
FROM
event e,location l
LEFT JOIN plusone p ON p.event_id = e.id_event
WHERE
e.location_id = l.id_location AND distance<=5 GROUP BY e.id_event
ORDER BY e.timestamp DESC,likes DESC
The huge column at the beginning is calculation of distance of the event from user position using latitude and longitude.
This is what I get from the SQL debugger:
#1054 - Unknown column 'distance' in 'where clause'
Does anybody know how to do this?
Is hard to track where the error is, you should try to solve the distance part first.
SELECT
event_id,
3956 * 2 * ASIN(SQRT( POWER(SIN((50.127946 - abs(l.lat)) * pi()/180 / 2),2)
+ COS(50.127946 * pi()/180 ) * COS(abs(l.lat) * pi()/180) * POWER(SIN((14.4882912 – l.lon) * pi()/180 / 2), 2) )) AS distance,
FROM event e
JOIN location l
WHERE distance <= 5
And then join to back to the event table
SELECT e.*, count(p.id_plusone)
FROM event e
LEFT JOIN plusone p
ON p.event_id = e.id_event
JOIN ( Previous Distance Query) d
ON e.event_id = d.event_id
GROUP BY e.id_event
ORDER BY e.timestamp DESC, likes DESC
and btw, this group_by will bring you event_id plus random values for e.* so be carefull
$latitudeD= latitude;
$longitudeD = longitude;
SELECT event,
SQRT(
POW(69.1 * (coordX - $latitudeD), 2) +
POW(69.1 * ($longitudeD - coordY) * COS(coordX / 57.3), 2)) AS distance
FROM db.table WHERE SQRT(
POW(69.1 * (coordX - $latitudeD), 2) +
POW(69.1 * ($longitudeD - coordY) * COS(coordX / 57.3), 2)) < 50 ORDER BY distance
;

How to avoid multiple column in correlated sub query assignment in MySQL update

I'm attempting to assign the closest location to a community based on the community postcode and using the Haversine formula with SQL described here. I need to return a single scalar value but I can't seem to avoid having the second calculated distance value which is needed to determine the closest location. Help.
UPDATE Community AS c
JOIN Postcode p on p.id = c.postcode_id
JOIN (
SELECT 100.0 AS radius, 111.045 AS distance_unit
) AS a
SET c.location_id = (
SELECT l.id,
a.distance_unit
* DEGREES(ACOS(COS(RADIANS(p.latitude))
* COS(RADIANS(l.latitude))
* COS(RADIANS(p.longitude - l.longitude))
+ SIN(RADIANS(p.latitude))
* SIN(RADIANS(l.latitude)))) AS distance
FROM Location AS l
WHERE l.latitude
BETWEEN p.latitude - (a.radius / a.distance_unit)
AND p.latitude + (a.radius / a.distance_unit)
AND l.longitude
BETWEEN p.longitude - (a.radius / (a.distance_unit * COS(RADIANS(p.latitude))))
AND p.longitude + (a.radius / (a.distance_unit * COS(RADIANS(p.latitude))))
HAVING distance <= a.radius
ORDER BY distance
LIMIT 1
)
Using the structure you have, you need to move the distance calculation into the WHERE and ORDER BY clauses:
SET c.location_id = (
SELECT l.id
FROM Location AS l
WHERE l.latitude
BETWEEN p.latitude - (a.radius / a.distance_unit)
AND p.latitude + (a.radius / a.distance_unit)
AND l.longitude
BETWEEN p.longitude - (a.radius / (a.distance_unit * COS(RADIANS(p.latitude))))
AND p.longitude + (a.radius / (a.distance_unit * COS(RADIANS(p.latitude))))
AND a.distance_unit
* DEGREES(ACOS(COS(RADIANS(p.latitude))
* COS(RADIANS(l.latitude))
* COS(RADIANS(p.longitude - l.longitude))
+ SIN(RADIANS(p.latitude))
* SIN(RADIANS(l.latitude)))) <= a.radius
ORDER BY a.distance_unit
* DEGREES(ACOS(COS(RADIANS(p.latitude))
* COS(RADIANS(l.latitude))
* COS(RADIANS(p.longitude - l.longitude))
+ SIN(RADIANS(p.latitude))
* SIN(RADIANS(l.latitude))))
LIMIT 1
)

MySQL using `IN` while having multiple values

I am trying to count of coupons sold by each store from the list of stores within 20 miles range. I know the following syntax will work if there is only 1 store.
SELECT sum(couponscount) as count where restaurant IN (SELECT storename where bhal bhal bhal and output is one value)
What is I the IN (SELECTstorenamewhere bhal bhal bhal and output is multiple values) will return multiple values?
Like in my case the complete SQL is like and its not working
SELECT sum(couponscount) as count FROM `coupons` having `restaurant` IN (SELECT `storename`, ((ACOS(SIN(-27.561264299999998 * PI()/180) * SIN(latitude * PI()/180) + COS(-27.561264299999998 * PI()/180) * COS(latitude * PI()/180) * COS((153.07304890000003 – longitude) * PI()/180)) *180 / PI( )) *60 * 1.1515) AS `distance` FROM `stores` WHERE `status`=’active’ HAVING `distance` <=20)
Is there anyway to make it working?
SELECT sum(couponscount) AS COUNT,restaurant
FROM `coupons`
WHERE `restaurant` IN
(SELECT `storename`
FROM `stores`
WHERE `status`='active'
AND
((ACOS(SIN(-27.561264299999998 * PI()/180) * SIN(latitude * PI()/180) + COS(-27.561264299999998 * PI()/180) * COS(latitude * PI()/180) * COS((153.07304890000003 – longitude) * PI()/180)) *180 / PI()) *60 * 1.1515) <=20)
GROUP BY restaurant
Also use proper quotes for active.
Presumably, you want to get the count of coupons from stores within a distance of 20. Moving the having condition to a where clause should do what you want:
SELECT sum(couponscount) as count
FROM `coupons`
WHERE `restaurant` IN (SELECT `storename`
FROM `stores`
WHERE `status` = 'active' AND
((ACOS(SIN(-27.561264299999998 * PI()/180) * SIN(latitude * PI()/180) + COS(-27.561264299999998 * PI()/180) * COS(latitude * PI()/180) * COS((153.07304890000003 – longitude) * PI()/180)) *180 / PI( )) *60 * 1.1515) <= 20
);
You had a major syntax problem because your subquery returned two columns. When you use a subquery with in, you can only return one column, in this case, storename. I moved the code for the distance calculation to the where clause. No having clause is needed either in the subquery or the outer query.