SQL query of Haversine formula in SQL server - sql

I am trying to get drivers who visited certain area from SQL server 2014 database. The table is named DriverLocationHistory.
Here is the sql query I used :
SELECT id, ( 6371 * acos( cos( radians(37) ) * cos( radians( latitude ) )
* cos( radians( Longitude ) - radians(-122) ) + sin( radians(37) ) * sin(radians(latitude)) ) ) AS distance
FROM DriverLocationHistory
HAVING distance < 5
ORDER BY distance
When I execute the query I get this error :
Msg 207, Level 16, State 1, Line 7
Invalid column name 'distance'.

I was asked to provide a way to do this with the built-in geography data type. That's a bit too long for a comment, so here goes:
ALTER TABLE [DriverLocationHistory] ADD geoLocation
AS geography::Point([Latitude], [Longitude], 4236);
declare #p geography = geography::Point(37, -122, 4236);
select * from [DriverLocationHistory]
where geoLocation.STDistance(#p) < 5000;
A spatial index should help with the SARGability of the where clause in the select.

You can't use an alias in a Where clause. This is because the where clause is processed before, or as, the result set is being generated, and the alias is not assigned until the result set has been generated. Only in an aggregate query (where there is a group By) can you do this, because then the alias is assigned to the value of some expression before the aggregation is processed. Your query must use the full expression in both the where clause (does not need to be a Having clause) and in the order by:
SELECT id,
( 6371 * acos( cos( radians(37) )
* cos( radians( latitude ) )
* cos( radians( Longitude ) - radians(-122) ) + sin( radians(37) )
* sin(radians(latitude)) ) ) AS distance
FROM DriverLocationHistory
Where 6371 * acos( cos( radians(37) )
* cos( radians( latitude ) )
* cos( radians( Longitude ) - radians(-122) ) + sin( radians(37) )
* sin(radians(latitude)) ) < 5
ORDER BY 6371 * acos( cos( radians(37) )
* cos( radians( latitude ) )
* cos( radians( Longitude ) - radians(-122) ) + sin( radians(37) )
* sin(radians(latitude)) )
as mentioned in comments, you can use the alias in the order by,
Or, you could also perform the computation and alias assignment in a subquery:
SELECT id, distance
From (Select ( 6371 * acos( cos( radians(37) )
* cos( radians( latitude ) )
* cos( radians( Longitude ) - radians(-122) ) +
sin( radians(37) )
* sin(radians(latitude)) ) ) distance
From DriverLocationHistory)z
Where distance < 5
ORDER BY distance

Related

Sequel: PG::UndefinedColumn: ERROR: column "distance" does not exist

I'm trying to get a list of businesses nearby using this query:
query = "SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS distance FROM businesses HAVING distance < ? ORDER BY distance"
After running this:
records = Api.DB.fetch(query, lng, lat, distance)
I get that PG::UndefinedColumn: ERROR: column "distance" does not exist.
distance isn't a column in the table but I created it as a calculated column in the query so it suppose to work but it's not?
Any ideas?
Postgres supports lateral joins, so you can do this without a subquery or CTE as:
SELECT b.id, v.distance
FROM business b CROSS JOIN LATERAL
(VALUES ( 3959 * acos( cos( radians(37) ) * cos( radians( b.lat ) ) * cos( radians( b.lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( b.lat ) ) )
)
) v(distance)
WHERE v.distance < ?
ORDER BY distance;
The query you are using was poached from MySQL, where select aliases can be used in a HAVING clause. But in Postgres, you will have to either subquery or just repeat the distance formula. Using the latter option as an example, here is one viable version of your Haversine query:
SELECT
id,
( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) ) AS distance
FROM business
WHERE
( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(?) ) + sin( radians(?) ) * sin( radians( lat ) ) ) )
< ?
ORDER BY
distance;

Unable to get nearest latitude and longitude from Sql Server Table

I want to apply the radius on nearest location. SQL query is working before HAVING clause. If I execute whole query then its giving error is :
"Invalid column name 'dist'."
My Sql query is:
SELECT name, latitude, longitude, ( 3959 * acos( cos( radians(30.901) ) * cos( radians( latitude ) ) *
cos( radians( longitude ) - radians(75.8573) ) + sin( radians(30.901) ) *
sin( radians( latitude ) ) ) ) AS dist
FROM res HAVING dist <= 25 ORDER BY dist ASC
I tried same above query. But that is half working. If I execute without HAVING clause then its working. Otherwise giving me an error:
"Invalid column name 'dist'".
having is for groupped data. use where instead.
use this :
SELECT *
FROM (
SELECT name, latitude, longitude, ( 3959 * acos( cos( radians(30.901) ) * cos( radians( latitude ) ) *
cos( radians( longitude ) - radians(75.8573) ) + sin( radians(30.901) ) *
sin( radians( latitude ) ) ) ) AS dist
FROM res
) myResult
WHERE myResult.dist <= 25
ORDER BY myResult.dist ASC
Use a subquery to define the columns, then select from that.
See if this works for you.
Select name, latitude, longitude, dist
From (
SELECT name, latitude, longitude, ( 3959 * acos( cos( radians(30.901) ) * cos( radians( latitude ) ) *
cos( radians( longitude ) - radians(75.8573) ) + sin( radians(30.901) ) *
sin( radians( latitude ) ) ) ) AS dist
FROM res ) A
WHERE dist <= 25 ORDER BY dist ASC

postgresql: input is out of range

I am trying to create a query to get the distance between 2 locations.
https://developers.google.com/maps/solutions/store-locator/clothing-store-locator
Sample from the link:
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;
Based on the sample link I have created the following query.
select ( 6371 * acos( cos( radians(3.139003) ) * cos( radians( 3.10726 ) ) * cos( radians( 101.60671 ) - radians(101.68685499999992) ) + sin( radians(3.139003) ) * sin( radians( 101.60671 ) ) ) ) AS distance from requests
Location 1: 3.139003, 101.68685499999992
Location 2: 3.10726, 101.60671
However, the query always failed with input is out of range, which seems to be due to acos.
Anyone can provide some pointers on this?
The last sin should be sin(radian(lat)) but you used the longitude instead. Replace sin( radians( 101.60671 ) with sin( radians( 3.10726 )
Yes, this is fairly trivial.
The argument to your leftmost acos function is
cos( radians(3.139003) )
* cos( radians( 3.10726 ) )
* cos( radians( 101.60671 )
- radians(101.68685499999992) )
+ sin( radians(3.139003) ) * sin( radians( 101.60671 ) )
which evaluates to 1.05066948199501.
But anything outside the range [-1,1] is not a valid argument for acos.
I know this doesn't particulary answer the question however this is the query i have saved for postgres that calculates the distance between 2 points in km using the haversine formula. I find its fairly simple and accurate.
SELECT asin(
sqrt(
sin(radians(latB - latA)/2)^2 +
sin(radians(lonB - lonA)/2)^2 *
cos(radians(latA)) *
cos(radians(latB))
)
) * (6371 * 2) AS distance;

Having/Where clause not working for Haversine Formula using Microsoft SQL

Here is my table named "test" -
Check the snapshot here test
And then my row items: here - rowitems
I'm using the haversine formula, he is my query
SELECT *, ( 3960 * acos( cos( radians( 33.650800 ) ) *
cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians( -117.891729 ) ) +
sin( radians( 33.650800 ) ) * sin( radians( Latitude ) ) ) ) AS Distance
FROM test
For some reason the HAVING or WHERE clause is not working with Distance.
It works with Latitude or Longitude.
But when I try to do WHERE Distance < 10 or HAVING Distance < 10. It says Distance is an invalid column name.
I need to be able to do this, and make a query using Distance. Any help would be appreciated.
You cannot use calculated fields on a where or having clause. Create a view or use a subquery
Try this:
select * FROM (SELECT *, ( 3960 * acos( cos( radians( 33.650800 ) ) *
cos( radians( Latitude ) ) * cos( radians( Longitude ) - radians( -117.891729 ) ) +
sin( radians( 33.650800 ) ) * sin( radians( Latitude ) ) ) ) AS Distance
FROM test) as T WHERE T.Distance < 10
You need to put your query into a subquery, or a view, or a CTE (common table expression).
Here is an example for your task with a CTE:
WITH cte_test (Name, Latitude, Longitude, Distance)
AS
(
SELECT Name, Latitude, Longitude,
3960 * acos(cos(radians(33.650800))
* cos(radians( Latitude ) )
* cos( radians( Longitude ) - radians( -117.891729 ) )
+ sin( radians( 33.650800 ) ) * sin( radians( Latitude ) ) ) )
AS Distance
FROM test
)
SELECT * from cte_test where Distance < 10 ;
A CTE is a kind of "temporary view". It is also a powerful instrument which can also be used for creating recursive queries.

get all markers within a given radius in sql

I'm trying to get all locations stored in the database with an sql statement described here
My sql statement is:
SELECT TOP(10)
*,
(
6371 *
acos(
cos(
radians(<cfqueryparam cfsqltype="CF_SQL_Numeric" value="#FORM.latitude#">)
) *
cos(
radians( custLat )
) *
cos(
radians( custLong ) -
radians(<cfqueryparam cfsqltype="CF_SQL_Numeric" value="#FORM.longtitude#">)
) +
sin(
radians(<cfqueryparam cfsqltype="CF_SQL_Numeric" value="#FORM.latitude#">)
) *
sin(
radians( custLat )
)
)
) AS distance
FROM customers
HAVING distance < 25
ORDER BY distance;
Problem is I get an error and can't figure out why...
error: Invalid column name 'distance'.
on this line: radians(<cfqueryparam cfsqltype="CF_SQL_Numeric" value="#FORM.latitude#">) (the second occurrence)
Why do I get this error and how do I fix it?
What you did it wrong. Here is solution :
SELECT distance FROM
(SELECT TOP(10)
*,
(
6371 *
acos(
cos(
radians(<cfqueryparam cfsqltype="CF_SQL_Numeric" value="#FORM.latitude#">)
) *
cos(
radians( custLat )
) *
cos(
radians( custLong ) -
radians(<cfqueryparam cfsqltype="CF_SQL_Numeric value="#FORM.longtitude#">)
) +
sin(
radians(<cfqueryparam cfsqltype="CF_SQL_Numeric" value="#FORM.latitude#">)
) *
sin(
radians( custLat )
)
)
) AS distance
FROM customers
) newTable
HAVING distance < 25
GROUP BY distance
ORDER BY distance;
You can solve it using creating a stored procedure or view in sql server or mysql server.