SQL ORDER BY distance not working properly - mysql

For the result on my page I need to order the results by distance. The page gets the current position of the user and retrieves the closest 30 results of that position.
Next to the order of the distance I also want to order the results for every venue by price.
Problem is that the price order works, but not the distance order. I can't figure out how my function is ordering the results because there is no structure in it (sometimes the closest result is on the last placing, sometimes it is in the middle, sometimes in the beginning, it's really weird).
My SQL statement looks like that:
$lat = '48.213688';
$lng = '16.408229';
$sql = "SELECT *, (3959 * acos(cos(radians('".$lat."')) * cos(radians(venue_address_lat)) * cos(radians(venue_address_lng) - radians('".$lng."')) + sin(radians('".$lat."')) * sin(radians(venue_address_lat)))) AS distance
FROM car_offer JOIN venues_infos ON car_offer.venues_infos_id = venues_infos.venue_id WHERE (3959 * acos(cos(radians('".$lat."')) * cos(radians(venue_address_lat)) * cos(radians(venue_address_lng) - radians('".$lng."')) + sin(radians('".$lat."')) * sin(radians(venue_address_lat)))) < 1.5
AND car_offer.offer_date = CURDATE()
AND venue_address_postcode = 1020
OR car_offer.offer_date = '0000-00-00'
ORDER BY distance, offer_price_small LIMIT 0,30";
The lat, lng in the database is from Google Maps, so this should be accurate.

I think you are better of using a outer query in this case and then do the order by in outer query like below. (OR) you can use the same distance calculation expression in your order by. Notice I have moved the distance < 1.5 from inner to outer query. Moreover, I am in doubt whether you can use distance in your order by clause like the way you are using (mean in the same query level unless it's from a derived table expression) since distance is a column alias.
SELECT * FROM
(
SELECT *, (3959 * acos(cos(radians('".$lat."')) * cos(radians(venue_address_lat)) * cos(radians(venue_address_lng) - radians('".$lng."')) + sin(radians('".$lat."')) * sin(radians(venue_address_lat)))) AS distance
FROM car_offer
JOIN venues_infos
ON car_offer.venues_infos_id = venues_infos.venue_id
WHERE car_offer.offer_date = CURDATE()
AND venue_address_postcode = 1020
OR car_offer.offer_date = '0000-00-00'
) tab
WHERE distance < 1.5
ORDER BY distance, offer_price_small
LIMIT 0,30

Related

Count locations withing given distance

I have the following query, that selects places withing given radius:
SELECT *
FROM (
SELECT
group,
name,
111.1111 *
DEGREES(ACOS(LEAST(1.0, COS(RADIANS(".$lat."))
* COS(RADIANS(t1.lat))
* COS(RADIANS(".$lon.") - RADIANS(t1.lon))
+ SIN(RADIANS(".$lat."))
* SIN(RADIANS(t1.lat))))) AS distance
FROM t1
) AS grp
WHERE distance < 10
Is there a way to count how many locations in each group withing this query?
In MySQL you can use HAVING to reduce the number of rows.
SELECT
`group`, COUNT(*) NumOfNames
FROM
(SELECT
`group`,
name,
ST_DISTANCE_SPHERE(POINT('.$lon.', '.$lat.'), POINT(t1.lon, t1.lat)) / 1000 AS distance
FROM
t1
HAVING distance < 10) t2
GROUP BY `group`

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

How can I run subqueries in mysql

I am trying to run subqueries from another table in a query
My Query is as follows:
SELECT *, (6371000 * acos(cos(radians(select point_oi.lng
from point_oi
where point_oi.name like '%Main Square%')
)
* cos(radians(restaurants.lat)) * cos(radians(restaurants.lng)
- radians(select point_oi.lng
from point_oi
where point_oi.name like '%Main Square%'
))
+ sin(radians(select point_oi.lng
from point_oi
where point_oi.name like '%Main Square%'))
* sin(radians(restaurants.lat)))) AS distance
FROM restaurants
HAVING distance < 500;
When I run the Query I get an error saying that there is an error near select.
I would like to use the nested select queries to get the lat and lng from another table rather than hardcoding the values.
How can I fix this.
Thank you for your help
You should not use subquery for retrieve point_poi lat, lnt if the suquery return more than a rows you have error ..
try use a proper join (in this case do the fatc you have not relation between point_poi and restaurants you could use cross join )
SELECT restaurants.*,
(6371000 * acos(cos(radians(point_oi.lng ))
* cos(radians(restaurants.lat)) * cos(radians(restaurants.lng)
- radians(point_oi.lng ))
+ sin(radians(point_oi.lng ))
* sin(radians(restaurants.lat)))) AS distance
FROM restaurants
CROSS JOIN point_oi
WHERE point_oi.name like '%Main Square%'
AND (6371000 * acos(cos(radians(point_oi.lng ))
* cos(radians(restaurants.lat)) * cos(radians(restaurants.lng)
- radians(point_oi.lng ))
+ sin(radians(point_oi.lng ))
* sin(radians(restaurants.lat)))) < 500;
Please try this query and let me know is your issue resolve.
SELECT t.*
,(6371000 * acos(cos(radians(SELECT point_oi.lng FROM point_oi WHERE point_oi.name LIKE '%Main Square%')) * cos(radians(restaurants.lat)) * cos(radians(restaurants.lng) - radians(SELECT point_oi.lng FROM point_oi WHERE point_oi.name LIKE '%Main Square%')) + sin(radians(SELECT point_oi.lng FROM point_oi WHERE point_oi.name LIKE '%Main Square%')) * sin(radians(restaurants.lat)))) AS distance
FROM restaurants As t
WHERE distance < 500;

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

MySQL Select Random X Entries - Optimized

MySQL what's the best way to select X random entries (rather than just one) - optimization for heavy use, i.e. on main page of a domain.
Supposedly just blindly using MySQL rand() is going to make this rather scary for large databases - please give me a better optimization answer than that!
the solution is use php
look at this article that choose the solution number 3 as faster
http://akinas.com/pages/en/blog/mysql_random_row/
Solution 3 [PHP]
$offset_result = mysql_query( " SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `table` ");
$offset_row = mysql_fetch_object( $offset_result );
$offset = $offset_row->offset;
$result = mysql_query( " SELECT * FROM `table` LIMIT $offset, 1 " )
the
Solution 4 [SQL] (Second in fast)
SELECT * FROM `table` WHERE id >= (SELECT FLOOR( MAX(id) * RAND()) FROM `table` ) ORDER BY id LIMIT 1;
I had an issue with the ids. The id was auto generated but the minimum id was very large with respect to the number of total records. So I made a little changes to make the query more randomized, but a little slower though.
SELECT * FROM 'table' WHERE id >= (SELECT (FLOOR( MAX(id) * RAND()) + MIN(id)) FROM 'table' ) ORDER BY id LIMIT 10