Seeking SQL syntax with errors using HAVING with assigned variable - sql

I am looking for the SQL syntax to use HAVING in the following statement:
DECLARE #ORIG_LAT AS FLOAT = 40.4882011413574;
DECLARE #ORIG_LONG AS FLOAT = -80.1939010620117;
DECLARE #DISTANCE AS INT;
SELECT LATITUDE_DEG, LONGITUDE_DEG,SQRT(
POWER(69.1 * (LATITUDE_DEG - #ORIG_LAT), 2) +
POWER(69.1 * (#ORIG_LONG - LONGITUDE_DEG) * COS(LATITUDE_DEG / 57.3), 2)) AS DISTANCE
FROM NAVAIDS
HAVING DISTANCE < 80 --error
ORDER BY DISTANCE ASC;
Error:
Msg 207, Level 16, State 1, Line 9
Invalid column name 'distance'.
It's ok with the ORDER BY but I don't understand why it doesn't like the HAVING. Any help with direction? It is SQL Server 2008 R2

As you have noticed, you can't use an aliased column directly. The easiest solution would be to wrap your statement in a subselect and apply your clause on that.
SELECT *
FROM (
SELECT LATITUDE_DEG
, LONGITUDE_DEG
, SQRT(
POWER(69.1 * (LATITUDE_DEG - #ORIG_LAT), 2) +
POWER(69.1 * (#ORIG_LONG - LONGITUDE_DEG) * COS(LATITUDE_DEG / 57.3), 2)) AS DISTANCE
FROM NAVAIDS
) q
WHERE DISTANCE < 80
ORDER BY
DISTANCE ASC;

select *
from (
SELECT LATITUDE_DEG, LONGITUDE_DEG, SQRT(
POWER(69.1 * (LATITUDE_DEG - #ORIG_LAT), 2)
POWER(69.1 * (#ORIG_LONG - LONGITUDE_DEG) * COS(LATITUDE_DEG / 57.3), 2)
) AS DISTANCE
FROM NAVAIDS
) a
WHERE DISTANCE < 80
ORDER BY DISTANCE

Related

The GROUP BY statement in my SQL query failed to get data

I'm writing an SQL query using GROUP BY, but on executing the GROUP BY statement, I get an error.
$data = DB::table('artisantypes')
->SELECT(DB::Raw("artisantypes.max_seat as max_size,3956 * 2 * ASIN(SQRT(POWER(SIN(('$current_lat' - artisans.driver_lat) * pi()/180 / 2), 2)+ COS('$current_lat' * pi()/180 ) * COS(artisans.driver_lat * pi()/180) * POWER(SIN(('$current_lng' - artisans.driver_lng) * pi()/180 / 2), 2) )) as distance,artisans.driver_lat,artisans.driver_lng" ))
->leftjoin('artisans','artisantypes.id', '=','artisans.car_id' )
->WHERE([['artisantypes.id' ,'=', $car_type],['artisans.artstatus', '=' , 0]])
->groupby('artisans.id')
->HAVING('distance' ,'<', 25)
->orderby ('distance', 'ASC' )
->LIMIT( 0,1)
->get();
Error
SQLSTATE[42000]: Syntax error or access violation: 1055
'sloyd.artisantypes.max_seat' isn't in GROUP BY

SQL -Place 2 decimal places in a runtime select -SQL

I have this select query :
SELECT Nombre, Tipo, Descripcion,Abierto,Cerrado, Latitud, Longitud,
SQRT( POW( 69.1 * ( Latitud - 19.55385 ) , 2 )
+ POW( 69.1 * ( - 99.21716 - Longitud )
* COS( Latitud / 57.3 ) , 2 ) ) AS distance
FROM Clientes
It works ok, but it sometimes returns a really long number (many decimal places) and I would like it to return the value with a decimal point with just two places.
I allready tried
CONVERT(DECIMAL(10,2),distance)
but I think my code is badly written.
It would be much appreciated if someone could give me an example or something!
Sorry for my english, I hope it's understandable. And thanks in advance!!
Use the function Round() to mathematical round and Cast to adjust the precision
Ex:
select Cast(ROUND(- 99.2171600000009669 ,2) as decimal(10,2))
Result
-99.22
In your query:
SELECT Nombre, Tipo, Descripcion,Abierto,Cerrado, Latitud, Longitud,
Cast(ROUND(SQRT( POW( 69.1 * ( Latitud - 19.55385 ) , 2 )
+ POW( 69.1 * ( - 99.21716 - Longitud )
* COS( Latitud / 57.3 ) , 2 ) ) ,2) as decimal(10,2)) AS distance
FROM Clientes
Order By Distance Desc

Convert Recursive CTE to Recursive Subquery

How would I convert the following CTE into a recursive subquery? It's an implementation of Newtons Method.
Reasons:
1) I have no permissions to create functions or stored procs in the DB
2) I must do everything in TSQL
3) Not using Oracle
TESTDATA Table
PMT t V
6918.26 6 410000
3636.51 14 460000
3077.98 22 630000
1645.14 18 340000
8591.67 13 850000
Desired Output
PMT t V Newton
6918.26 6 410000 0.066340421
3636.51 14 460000 0.042449138
3077.98 22 630000 0.024132674
1645.14 18 340000 0.004921588
8591.67 13 850000 0.075982984
_
DECLARE #PMT AS FLOAT
DECLARE #t AS FLOAT
DECLARE #V AS FLOAT
--These will be only for 1 example.
SET #PMT = 6918.26740930922
SET #t = 6
SET #V = 410000
;With Newton (n, i,Fi,dFi) AS (
--base
SELECT
1,
CAST(0.1 AS FLOAT)
,#PMT * (1 - POWER((1 + CAST(0.1 AS FLOAT) / 12), (-#t * 12))) - #V * CAST(0.1 AS FLOAT) / 12
,#PMT * #t * 12 * POWER((1 + CAST(0.1 AS FLOAT) / 12), (-#t * 12 - 1)) - #V
UNION ALL
--recursion
SELECT
n + 1
,i - Fi/dFi
,#PMT * (1 - POWER((1 + i / 12), (-#t * 12))) - #V * i / 12
,#PMT * #t * 12 * POWER((1 + i / 12), (-#t * 12 - 1)) - #V
FROM Newton WHERE n < 500)
--to get the desired value for params above
SELECT [x].i
FROM (
SELECT n, i, Fi, dFi
FROM Newton
WHERE n = 500
) [x]
OPTION (MAXRECURSION 500)
_
I want Newton to evaluate on Every record of TestData as a stand alone column.
Any thoughts?

find the nearest location by latitude and longitude in postgresql

Hi i'm trying find the nearest location by latitude and longitude in postgresql database.But when i run the below query it showing column distance does not exists.
ERROR: column "distance" does not exist
LINE 1: ... ) ) ) AS distance FROM station_location HAVING distance <...
^
********** Error **********
ERROR: column "distance" does not exist
SQL state: 42703
Character: 218
CREATE TABLE station_location
(
id bigint NOT NULL DEFAULT nextval('location_id_seq'::regclass),
state_name character varying NOT NULL,
country_name character varying NOT NULL,
locality character varying NOT NULL,
created_date timestamp without time zone NOT NULL,
is_delete boolean NOT NULL DEFAULT false,
lat double precision,
lng double precision,
CONSTRAINT location_pkey PRIMARY KEY (id)
)
SELECT *,( 3959 * acos( cos( radians(6.414478) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(12.466646) ) + sin( radians(6.414478) ) * sin( radians( lat ) ) ) ) AS distance
FROM station_location
HAVING distance < 5
ORDER BY distance
LIMIT 20;
PostGIS
Don't store lat and long on a table like that. Instead use an PostGIS geometry or geography type.
CREATE EXTENSION postgis;
CREATE TABLE foo (
geog geography;
);
CREATE INDEX ON foo USING gist(geog);
INSERT INTO foo (geog)
VALUES (ST_MakePoint(x,y));
Now when you need to query it, you can use KNN (<->) which will actually do this on an index.
SELECT *
FROM foo
ORDER BY foo.geog <-> ST_MakePoint(x,y)::geography;
In your query, you explicitly have HAVING distance < 5. You can do that on the index too.
SELECT *
FROM foo
WHERE ST_DWithin(foo.geog, ST_MakePoint(x,y)::geography, distance_in_meters)
ORDER BY foo.geog <-> ST_MakePoint(x,y)::geography;
This ensure that nothing is returned if all points lie outside of distance_in_meters.
Furthermore x and y are decimal numbers ST_MakePoint(46.06, 14.505)
select * from (
SELECT *,( 3959 * acos( cos( radians(6.414478) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(12.466646) ) + sin( radians(6.414478) ) * sin( radians( lat ) ) ) ) AS distance
FROM station_location
) al
where distance < 5
ORDER BY distance
LIMIT 20;
You can use PostgreSQL's cube and earthdistance extensions.
Enable them like this:
CREATE EXTENSION cube;
CREATE EXTENSION earthdistance;
Let's say your current location is 35.697933, 139.707318. Then your query will be something like this:
SELECT *, point(35.697933, 139.707318) <#> (point(longitude, latitude)::point) as distance
FROM station_location
-- WHERE (point(35.697933, 139.707318) <#> point(longitude, latitude)) < 3
ORDER BY distance;
Please note that the distance is in miles (by default).
See this gist, you will find how to declare a DOMAIN on the point type and how to override the distance operator to return the orthodromic distance.
Declare a latlong type inherited from point:
CREATE DOMAIN latlong AS point CHECK (VALUE[0] BETWEEN -90.0 AND 90.0 AND VALUE[1] BETWEEN -180 AND 180);
The orthodromic distance in kilometers (distance on a sphere with the earth radius):
CREATE OR REPLACE FUNCTION orthodromic_distance(latlong, latlong) RETURNS float AS $_$
SELECT acos(
sin(radians($1[0]))
*
sin(radians($2[0]))
+
cos(radians($1[0]))
*
cos(radians($2[0]))
*
cos(radians($2[1])
-
radians($1[1]))
) * 6370.0;
$_$ LANGUAGE sql IMMUTABLE;
Override the distance operator <-> using this function when used with latlongs:
CREATE OPERATOR <-> ( PROCEDURE = orthodromic_distance
, LEFTARG = latlong, RIGHTARG = latlong
);
Now in your SQL queries, to find the nearest entities:
WITH
station_distance AS (
SELECT
id AS station_id,
point(lat, long)::latlong <-> point(6.414478, 12.466646)::latlong AS distance
FROM station_location
WHERE NOT is_deleted
)
SELECT
sl.state_name,
sl.country_name,
sl.locality,
point(sl.lat, sl.long)::latlong AS coordinates,
sd.distance
FROM
station_location sl
JOIN station_distance sd
ON sd.station_id = sl.id
ORDER BY
distance ASC
LIMIT 10
You probably want to store the position lat and long in the same field using the latlong type.
The manual clarifies :
An output column's name can be used to refer to the column's value in
ORDER BY and GROUP BY clauses, but not in the WHERE or HAVING clauses;
there you must write out the expression instead.

How do i call a stored procedure or stored function from sql select statement

I have created following stored user defined it gets executed successfully.
CREATE FUNCTION spherical_distance1(#a float, #b float, #c float , #Lat float, #Lng float)
RETURNS float
AS
BEGIN
RETURN ( 6371 * ACOS( COS( #a/#b ) * COS( #Lat/#b ) * COS( #Lng/#b - #c/#b ) + SIN( #a/#b ) * SIN( #Lat/#b )))
END
The problem i am facing is here, when i call stored function spherical_distance1 ,it shows error like 'spherical_distance1' is not a recognized built-in function name.
SELECT *, spherical_distance1(12.9216667, 57.2958, 77.591667, Lat, Lng) AS distance
FROM business3
WHERE distance < 3
AND StreetName LIKE '%jayanagar %'
AND Keyword LIKE '%plumbing %'
ORDER BY spherical_distance1(12.9216667, 57.2958, 77.591667, Lat, Lng);
In SQL server, you need to prefix function names with the schema.
Most likely, yours will be dbo, so try calling
select *,
dbo.spherical_distance1(12.9216667 ,57.2958,77.591667,Lat ,Lng) as distance
from
business3
where
(( distance < 3 ) and (StreetName like '%jayanagar %') and (Keyword like '%plumbing %' ))
order by
distance -- don't need to repeat the function here
First mistake - it's a USERFUNCTION not a STOREDPROCEUDRE
Second - to call the user function you have to use
SELECT dbo.functionName()
so for your case
SELECT dbo.spherical_distance1(12.9216667, 57.2958, 77.591667, Lat, Lng) AS distance
you need to include "dbo." before function name in your query...