Use a second ORDER by in MySQL query - mysql

I am using the following query to select the nearest rows to a specified latitude and longitude. The results are then ordered by distance, returning the nearest rows out of the selected data set.
However, I would like to then order the returned nearest rows by the expiry_date field to order that data set so that I will have the ending soonest (nearest expiry date) at the top and furthest at the bottom.
Please can you tell me how I can do this?
SELECT * , ( 6371 * ACOS( COS( RADIANS( latitude ) ) * COS( RADIANS( 51.61062 ) ) * COS( RADIANS( - 0.236952 ) - RADIANS( longitude ) ) + SIN( RADIANS( latitude ) ) * SIN( RADIANS( 51.61062 ) ) ) ) AS distance
FROM `questions`
WHERE `expiry_date` >
CURRENT_TIMESTAMP HAVING distance <=50000
ORDER BY distance
LIMIT 0 , 15

ORDER BY can be a comma separated list. Just list them by order of presdence:
SELECT * , ( 6371 * ACOS( COS( RADIANS( latitude ) ) * COS( RADIANS( 51.61062 ) ) * COS( RADIANS( - 0.236952 ) - RADIANS( longitude ) ) + SIN( RADIANS( latitude ) ) * SIN( RADIANS( 51.61062 ) ) ) ) AS distance
FROM `questions`
WHERE `expiry_date` >
CURRENT_TIMESTAMP HAVING distance <=50000
ORDER BY distance
, expiry_date DESC
LIMIT 0 , 15

You need a subquery:
select t.*
from (<your query here>) t
order by expiry_date desc

Related

MySQL - Using COUNT() to return total results when HAVING is specified

Using the query below, I can search for properties within a given radius and results are returned.
SELECT id, address, ( 3959 * acos( cos( radians( 53.184815 ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-3.025741) ) + sin( radians(53.184815) ) * sin( radians( lat ) ) ) ) AS distance
FROM properties
WHERE area = 1 HAVING distance <= 1
ORDER BY price DESC, distance ASC
LIMIT 0, 10
However I now want to add pagination, thus the "LIMIT 0, 10" but somehow have the query return the total results. For example, if there are 100 results but we're only limiting to the first 10 results, return the total as 100.
I tried adding "COUNT(*) AS total" after the select but this caused zero results to be returned.
How do I have the query return the total in this way?
I think it will need a subquery to achieve that:
SELECT
id, address, ( 3959 * acos( cos( radians( 53.184815 ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-3.025741) ) + sin( radians(53.184815) ) * sin( radians( lat ) ) ) ) AS distance,
(SELECT count(*) FROM properties WHERE area = 1 HAVING ( 3959 * acos( cos( radians( 53.184815 ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-3.025741) ) + sin( radians(53.184815) ) * sin( radians( lat ) ) ) )<= 1) AS total
FROM properties
WHERE area = 1 HAVING distance <= 1
ORDER BY price DESC, distance ASC
LIMIT 0, 10
You either have to use a separate query without limit with count(*) or as splash indicated, use SQL_CALC_FOUND_ROWS in your query and then issue a SELECT FOUND_ROWS(); to get the total number.
You can try to inject the count(*) query as a subquery in your main query, but to me that's only unnecessary complication of your query.

Haversine formula returns null in Query

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

Why won't this query return results that are 0?

Using haversine, the following query finds all rows that have coordinates within a 10 mile radius of the inputted coordinates.
SELECT *
, ( 3959 * acos( cos( radians($locationLatitude) )
* cos( radians( endingLatitude ) )
* cos( radians( endingLongitude ) - radians( $locationLongitude ) )
+ sin( radians( $locationLatitude) )
* sin( radians( endingLatitude ) ) ) ) AS distance
FROM trips
HAVING distance < 10
ORDER
BY distance
LIMIT 0 , 10;
However, it does not return rows that have the same exact coordinates as the coordinates inputted. Why is this?
You're using incorrect syntax: Change HAVING to WHERE and use a subquery so you can refer to the alias of the calculation rather than having to repeat the formula:
select * from (
select *, ( 3959 * acos( cos( radians($locationLatitude) )
* cos( radians( endingLatitude ) )
* cos( radians( endingLongitude ) - radians( $locationLongitude ) )
+ sin( radians( $locationLatitude) )
* sin( radians( endingLatitude ) ) ) ) AS distance
from trips) x
WHERE distance < 10
ORDER BY distance
LIMIT 0, 10
HAVING is for conditions on aggregated values for groups, eg GROUP BY FOO HAVING COUNT(*) > 3, but you aren't doing any grouping; you need a simple where clause.
Unfortunately, mysql has "lenient" grouping syntax which has allowed your statement to execute without a syntax error, even though it is logically unsound. The same query run on other databases would cause an error.

Virtual column unknown when comparing lat lng

I am attempting to return only rows where the latitude and longitude being passed into the query, when compared to the latitude and longitude stored in the database, is a certain amount of miles apart.
The query is as follows:
SELECT
c.google_theatre_id
AS cinema_id,
c.name
AS cinema_name,
( 3959 * acos( cos( radians('50.4521013') ) *
cos( radians( latitude ) ) *
cos( radians( longitude ) -
radians('-3.5247389') ) +
sin( radians('50.4521013') ) *
sin( radians( latitude ) ) ) )
AS distance
FROM
google_cinemas c, app_users u
WHERE
distance < u.range
AND
u.id = 126
ORDER BY
distance
The query is designed to get the distance and then compare it to a column (range) in the app_users table.
When running the query, I'm getting an error of distance being an unknown column.
As this is a virtual column, is there a different way of comparing?
Thanks :)
you need to use HAVING instead of WHERE.. think of it this way WHERE is when you make an order at a restraunt and HAVING is picking stuff off of the plate when it comes to your table... you cannot reference an alias before the plate comes to your table only after it has been built
SELECT
c.google_theatre_id AS cinema_id,
c.name AS cinema_name,
( 3959 * acos( cos( radians('50.4521013') ) *
cos( radians( latitude ) ) *
cos( radians( longitude ) -
radians('-3.5247389') ) +
sin( radians('50.4521013') ) *
sin( radians( latitude ) ) )
) AS distance
FROM google_cinemas c, app_users u
WHERE u.id = 126
HAVING distance < u.range
ORDER BY distance
alternatively you can use it as a sub query which could be faster since HAVING re-evaluates the entire query.
SELECT *
FROM
( SELECT
c.google_theatre_id AS cinema_id,
c.name AS cinema_name,
( 3959 * acos( cos( radians('50.4521013') ) *
cos( radians( latitude ) ) *
cos( radians( longitude ) -
radians('-3.5247389') ) +
sin( radians('50.4521013') ) *
sin( radians( latitude ) ) )
) AS distance,
u.range
FROM google_cinemas c, app_users u
WHERE u.id = 126
ORDER BY distance
)t
WHERE distance < range

Combining multiple where conditions in mysql SELECT query

So here's my issue:
I have a database table where I have latitudes and longitudes and a timestamp. I need to be able to search through this table using PHP. What would the query be to find rows with lats and lons in a certain range, and, on top of this, in a certain time frame.
I have found two separate queries that would work while browsing through the internet, but I can't find a clear way to combine multiple conditions.
The two queries are:
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) *
cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) *
sin( radians( lat ) ) ) ) AS distance
FROM markers
HAVING distance < 25
ORDER BY distance
LIMIT 0 , 20;
enter code here
SELECT * FROM `table` WHERE `date_field` BETWEEN 'date1' AND 'date2'
I need to find top twenty results where timestamp and lat and long are in range.
Thanks!
EDIT: All fields are in the same table.
If all data is in the same table, you can do:
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance
FROM markers
WHERE date_field BETWEEN 'date1' AND 'date2'
HAVING distance < 25
ORDER BY distance
LIMIT 0 , 20;