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;
Related
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.
I've looked and looked and tried and tried with no success. I have a query that I use to display users within a certain distance range. It works great, but it returns all users from my users table, and I want it to only return users where the value in account_type is equal to '1'. So basically different kinds of account types share my users table and on this page I only want one type of user to be display. I've tried all sorts of things, including joining the same table which I know makes no sense and it didn't work anyway. Basically, I would like to know where in this query I can add a 'WHERE' clause to check the column named 'account_type'.
Here's my functional query:
SELECT `user_id`, ( 3959 * acos( cos( radians('".$lat."') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('".$lng."') ) + sin( radians('".$lat."') ) * sin( radians( lat ) ) ) ) AS distance FROM users HAVING distance <= '".$dist."' ORDER BY distance
Since I only want to return users from that table that have account_type = 1, I tried doing many different variations of the following, with no success:
SELECT `user_id`, `account_type`, ( 3959 * acos( cos( radians('".$lat."') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('".$lng."') ) + sin( radians('".$lat."') ) * sin( radians( lat ) ) ) ) AS distance FROM users ***WHERE `account_type` = '1'*** HAVING distance <= '".$dist."' ORDER BY distance
SELECT `user_id`, `account_type`, ( 3959 * acos( cos( radians('".$lat."') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('".$lng."') ) + sin( radians('".$lat."') ) * sin( radians( lat ) ) ) ) AS distance FROM users HAVING distance <= '".$dist."' ***WHERE `account_type` = '1'*** ORDER BY distance
any many others though I won't pollute this topic any further. Can someone please tell me what I'm doing wrong? Thank you
#rhavendc was correct. I'm a moron. The account that I created to test this I used some far away location and though there are more than 20 test accounts on my site, there were none within 100miles of the crazy location my test account was using as far as those matching account_type='1'
So once I realized that it took 2 seconds to just use this query to get the proper result
$qry="SELECT user_id, ( 3959 * acos( cos( radians('".$lat."') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians('".$lng."') ) + sin( radians('".$lat."') ) * sin( radians( lat ) ) ) ) AS distance FROM users WHERE account_type = '1' HAVING distance <= '".$dist."' ORDER BY distance";
Thanks for everyone's input. I apologize for my stupidity.
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.
I have a MySQL database with the following table
int - id
float 2,6 - long
float 2,6 - lat
int - radius
I want to create a SQL query which returns the ID & Distance from a given location(long & lat)
I found the following piece of code which works:
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;
I want to alter this query to return only the rows where the computed length is smaller the radius (a column i my table)
replacing the 25 with the radius doesn't work.
Is there a way to achieve that without using two SQL queries ?
problem is occured because the result distance is in float and radius is an integer datatype so you need to CAST radius as float. try below
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 < CAST (radius AS float) ORDER BY distance LIMIT 0 , 20;
HAPPY TO HELP :)
I have this query:
SELECT
count(*) as count ,
( 3959 * acos(
cos( radians( 37.774929 ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians( -122.419418 ) )
+ sin( radians( 37.774929 ) ) * sin( radians( lat ) )
) ) AS distance
FROM users
HAVING distance < 150
I thought it was going to give me the count of users who are in the radius of 150 miles. But instead it gave me a total number of users. And if lat/lng were different, it would give me zero number of users when there were some users there.
Any ideas how to change this query in order to get the number of users within the 150mi radius?
Thanks!
You want to use a WHERE clause
select count(*) as count from users WHERE ( 3959 * acos( cos( radians( 37.774929 ) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians( -122.419418 ) ) + sin( radians( 37.774929 ) ) * sin( radians( lat ) ) ) ) < 150
To expand on Dirk's answer...
The WHERE clause is applied to the records after they've all be joined up.
The HAVING clause is applied after any aggregation is complete.
Also, as in Dirk's answer, you don't need to have the calculation in the SELECT to be able to use it elsewhere.
So, Dirk's answer calculates the Distance for each individual ROW (after joins, before aggregation), then discards any with a distance of 150 or more. It only THEN aggregates and counts everything up.