I used the following sql for mySQL but I now need to use this for a Firebird database. I have searched and read the Firebird documentation but can't seem to locate an alternative. In Firebird 'radians' and 'limit' both are not supported. Has anyone successfully done similar in Firebird?
SELECT zip, ( 3959 * acos( cos( radians(38.6285426) ) * cos( radians( lat ) )
* cos( radians( lng ) - radians(-86.05296039999999) ) + sin( radians(38.6285426) ) * sin(radians(lat)) ) ) AS distance
FROM zipcodes
HAVING distance < 25
ORDER BY distance
LIMIT 0 , 20;
The radians function in mySQL "returns the argument X, converted from degrees to radians". You don't need builtin function to do that, it's rather simple math: radians = degrees × π / 180º. You could create an convenience view with calculated columns for deg-to-rad conversion, to make the query easier to read. BTW, Firebird has builtin function for retrieving π value.
Instead of LIMIT Firebird supports ROWS syntax:
SELECT <columns> FROM ...
[WHERE ...]
[ORDER BY ...]
ROWS <m> [TO <n>]
For anyone having a similar issue, here was my solution for Firebird that returns all zips codes within a certain mile radius of a Lat/long (Great Circle) in one query.
select zipcode from(
SELECT zipcode, ( 3959 * acos( cos( 38.6285426/57.2958 ) * cos( lat/57.2958 )
* cos( lon/57.2958 - -86.05296039999999/57.2958 ) + sin( 38.6285426/57.2958 ) * sin(lat/57.2958) ) ) AS distance
FROM zip_codes)
where distance < 20
ORDER BY distance
Related
I have the following query which does indeed work. It takes in a hard set Latitude and Longitude and finds the closest set of coordinates, along with it's postal code.
What I'm having trouble with is the speed of the query. It's currently taking 3.8 seconds to run and I have 9000 separate coordinates to check.
Any advice on how to speed this up would be greatly appreciated.
SELECT pcds, ROUND(MIN(distance), 4) AS distance FROM
(SELECT `postcode`.`pcds`,(
6371 * acos (
cos ( radians('51.4932392') )
* cos( radians( `postcode`.`lat` ) )
* cos( radians( `postcode`.`lng` ) - radians('-0.0846429') )
+ sin ( radians('51.4932392') )
* sin( radians( `postcode`.`lat` ) )
)
) AS distance
FROM postcode
ORDER BY distance
LIMIT 1
) AS First
I have a table of cities with, among other things, population, latitude and longitude. I also have a table of airports with various info including latitude and longitude.
A query like this roughly obtains the population of all towns within 100 km of a given latitude and longitude:
SELECT SUM(cty_population) as cty_population_total FROM
(SELECT
cty_population, (
6371 * acos (
cos ( radians(37.61899948) )
* cos( radians( cty_latitude ) )
* cos( radians( cty_longitude ) - radians(-122.37500000) )
+ sin ( radians(37.61899948) )
* sin( radians( cty_latitude ) )
)
) AS cty_distance
FROM cities
HAVING cty_distance < 100) cty_population_alias
This will give a result like this:
cty_population_total
6541221
In the above query, 37.61899948 is the latitude and -122.37500000 is the longitude.
My question is: can I select an arbitrary number of airports from the airports table, pass their longitudes and latitudes into this subquery in place of the above numbers, and find the city population within 100 km of each airport. Ideally I would have results like this:
airport_name airport_pop
Boston Logan 6654901
London Heathrow 11345690
...etc.
I could do this with scripting, but I am wondering if it can be done with SQL alone? The database engine is MySQL.
You have a very procedural way of thinking this which would not work well in SQL. You can think of it as joining the city with all its nearby airports.
The following may work:
SELECT a.name, SUM(c.cty_population)
FROM cities c JOIN airports a ON (
6371 * acos (
cos ( radians(a.latitude) )
* cos( radians( c.cty_latitude ) )
* cos( radians( c.cty_longitude ) - radians(a.longitude) )
+ sin ( radians(a.latitude) )
* sin( radians( c.cty_latitude ) )
) < 100
WHERE (filter airports or something else here)
GROUP BY a.airport_id, a.name
Also, I suggest you migrate to MySQL 5.7 which includes spatial functions and data types built in.
I'm having a difficult time wrapping my head around how to do this, even with all the searching and reading I've done on this!
I have a query I am using to try to pull all users from a database that have a zip code that falls within a certain distance of a given decimal coordinate. Here's the query that I am running:
select distinct watch_list.username, enabled
from watch_list, registered_users
where watch_list.username = registered_users.username AND watch_list.watchzip = (
SELECT zip,
( 3959 * acos( cos( radians('29.7632800') ) *
cos( radians( lat ) ) *
cos( radians( lng ) -
radians('-95.3632700') ) +
sin( radians('29.7632800') ) *
sin( radians( lat ) ) ) )
AS distance from zip
HAVING distance <= '10');
There error I get back is expected, as my sub query is returning two columns:
MySQL said: Documentation
#1241 - Operand should contain 1 column(s)
How can I do this and filter on the distance without the sub query returning both columns?
P.S. Just for completion and information sake, the "zip" table contains a list of all zip codes in the U.S. along with their decimal coordinates.
Just move the operation out of the column list:
select distinct watch_list.username, enabled
from watch_list, registered_users
where watch_list.username = registered_users.username
AND watch_list.watchzip = (
SELECT zip
from zip
WHERE ( 3959 * acos( cos( radians('29.7632800') ) *
cos( radians( lat ) ) *
cos( radians( lng ) -
radians('-95.3632700') ) +
sin( radians('29.7632800') ) *
sin( radians( lat ) ) ) ) <= '10');
Edit: As P.Salmon mentions, you probably also want to change AND watch_list.watchzip = to AND watch_list.watchzip IN.
This may or may not be a simple question.
I have a query which selects all locations within a mile radius around a provided latitude and longitude. That part works perfectly, but I have additional information inside of another table that I would like to match to it. I've tried LEFT JOIN, but it's timing out.
SELECT *,
( 3959 * acos( cos( radians(40.7143528) ) * cos( radians( lat ) )
* cos( radians( lon ) - radians(-74.0059731) ) + sin( radians(40.7143528) )
* sin( radians( lat ) ) ) ) AS distance
FROM locations
LEFT JOIN informations ON
locations.name = informations.name
HAVING distance < 1
Here is what I would like this query to do:
Provide all matching locations within a mile radius (works)
Obtain the name of those stores (works)
Match those names against the names of each store in the "informations" table
Join all of the information in the matching rows together, where "locations.name" and "informations.name" match
The above query seems like it wants to work. I don't get any errors and it shows as valid in any MySQL formatter I use. However, I think I'm making an error somewhere which causes my tiny server to max processor usage.
To a more experienced set of eyes, would you see a reason why this would occur? Other than my server being near useless, of which I'm aware.
Make your initial query a sub-query of the main query, and left join that resulting relation to the new table (with additional information). That should give you performance back
The result will look like this:
SELECT *
FROM(
SELECT *,
( 3959 * acos( cos( radians(40.7143528) ) * cos( radians( lat ) )
* cos( radians( lon ) - radians(-74.0059731) ) + sin( radians(40.7143528) )
* sin( radians( lat ) ) ) ) AS distance
FROM locations
) locations
LEFT JOIN informations
ON location.name =informations.name
The HAVING clause is of course part of query #1.
I use SQL SERVER typically, so the syntax may not be quite right for MYSQL.
I am attempting to use the Haversine formula. Ideally, I would like to use Hibernate provider with JPA and MySQL. This is the following query that I am using which appears to work in MySQL.
SELECT campusid, ( 3959 * acos( cos( radians(37) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-122) ) + sin( radians(37) ) * sin( radians( latitude ) ) ) ) AS distance FROM mydb.campus HAVING distance < 25 ORDER BY distance LIMIT 0 , 20;
I am trying to see how I could use Hibernate and would like a cleaner way of doing this. I looked at the Criteria API but can't seem to find a way to execute this.
That query is unlikely to be possible in Hibernate and certainly not in a clean way. You can however execute a native SQL query.
session.createSQLQuery("your sql here");
This will tie you to MySQL but should work.