How to generate numbers with a normal distribution in SQL Server - sql-server

I'm trying to seed some data, is there anyway to generate numbers in SQL Server that follow a normal distribution curve?
Like: I will specify the mean, the standard deviation and the count and I get a list of numbers back?

random normal distribution
UPDATE TABLE
SET COLUMN = CAST(SQRT(-2*LOG(RAND()))*SIN(2*PI()*RAND(CHECKSUM(NEWID())))as decimal(5,3))
from TABLE

quoting from http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=135026 you might try with
CREATE FUNCTION [dbo].[udf_NORMSDIST]
(
#x FLOAT
)
RETURNS FLOAT
AS
/****************************************************************************************
NAME: udf_NORMSDIST
WRITTEN BY: rajdaksha
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=135026
DATE: 2009/10/29
PURPOSE: Mimics Excel's Function NORMSDIST
Usage: SELECT dbo.udf_NORMSDIST(.5)
REVISION HISTORY
Date Developer Details
2010/08/11 LC Posted Function
*****************************************************************************************/
BEGIN
DECLARE #result FLOAT
DECLARE #L FLOAT
DECLARE #K FLOAT
DECLARE #dCND FLOAT
DECLARE #pi FLOAT
DECLARE #a1 FLOAT
DECLARE #a2 FLOAT
DECLARE #a3 FLOAT
DECLARE #a4 FLOAT
DECLARE #a5 FLOAT
--SELECT #L = 0.0
SELECT #K = 0.0
SELECT #dCND = 0.0
SELECT #a1 = 0.31938153
SELECT #a2 = -0.356563782
SELECT #a3 = 1.781477937
SELECT #a4 = -1.821255978
SELECT #a5 = 1.330274429
SELECT #pi = 3.1415926535897932384626433832795
SELECT #L = Abs(#x)
IF #L >= 30
BEGIN
IF sign(#x) = 1
SELECT #result = 1
ELSE
SELECT #result = 0
END
ELSE
BEGIN
-- perform calculation
SELECT #K = 1.0 / (1.0 + 0.2316419 * #L)
SELECT #dCND = 1.0 - 1.0 / Sqrt(2 * #pi) * Exp(-#L * #L / 2.0) *
(#a1 * #K + #a2 * #K * #K + #a3 * POWER(#K, 3.0) + #a4 * POWER(#K, 4.0) + #a5 * POWER (#K, 5.0))
IF (#x < 0)
SELECT #result = 1.0 - #dCND
ELSE
SELECT #result = #dCND
END
RETURN #result
END
You can obviously offset the results to change the mean and wrap this in a function to iterate as needed to return the desired number of sample points. Let me know if you need help for this.

For instance (stupid SO body parser):
http://www.sqlservercentral.com/articles/SQL+Uniform+Random+Numbers/91103

Related

How do I get divided 6 columns equal 100%?

I have a problem with dividing in SQL Server.
I am dividing 100/6.00. And it gives me 16.67, 16.67, 16.67, 16.67, 16.67, 16.67
Which is 100.02 at the end.
Is there a way to divide 100/6.00 and get 16.66, 16.66, 16.67, 16.67, 16.67, 16.67 as a result?
I don't look for solution like iif(final sum>100) then . Is there other way to do this?
Thanks
If you want exact division, then the general answer here is to use an exact type, such as NUMERIC or DECIMAL. Consider:
WITH yourTable AS (
SELECT CAST(100.0 AS NUMERIC(10, 2)) AS num
)
SELECT num / 6 AS output -- output is 16.666666
FROM yourTable;
...test
declare #amount decimal(9,4) = 100;
declare #den decimal(9,4) = 6.00;
declare #dp tinyint = 2; --decimal points for rounding
select val as colid,
round(#amount/ceiling(#den), #dp,1) +
case when val <= power(10, #dp) * ((#amount- ceiling(#den) * round(#amount/ceiling(#den), #dp,1))%ceiling(#den)) then power(10.0000000000, -#dp)
else 0.00000 end
from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) as v(val) --max denominator:10
where val <= ceiling(#den);
Can this somehow help you?
DECLARE #counter numeric(5,2)
DECLARE #row int
DECLARE #number numeric(2,1)
SET #counter= 100
SET #number = 6.0
SET #row = 1
while #counter != 0
BEGIN
select #counter,#number,#row,#counter/#number
set #counter = #counter - #counter/#number
set #number = #number - 1
set #row = #row + 1
END

Linear interpolation with Variables in T-SQL

Input to my procedur
#time datetime -- Example: 27.07.2015 01:00
With some SELECT staments I get the following information
#prevTime datetime -- Example: 27.07.2015 00:00
#prevValue real -- Example: 1
#nextTime datetime -- Example: 27.07.2015 02:00
#nextValue real -- Example: 3
Now I want to calculate
#value real -- In this Example the result should be: 2
i want to use "linear interpolation", see here: https://en.wikipedia.org/wiki/Linear_interpolation
Can someone tell me, how this gets done best? (Can i just convert the datetime into real?)
EDIT:
My first Quick&Dirty Idea:
SET #value = #prevValue + ((#nextValue-#prevValue)/(CAST(#nextTime as real)-CAST(#prevTime as real))) * (CAST(#time as real)-CAST(#prevTime as real));
Don't work, because datetime -> real is not precise
My second Quick&Dirty Idea:
SET #value = #prevValue + ((#nextValue-#prevValue)/(DATEDIFF(second,#nextTime,GETDATE())-DATEDIFF(second,#prevTime,GETDATE()))) * (DATEDIFF(second,#time,GETDATE())-DATEDIFF(second,#prevTime,GETDATE()));
Work's, but i would be happy if someone told me a nicer way
I'd submitted such code previously to SQL Server central as a code example at http://www.sqlservercentral.com/Forums/Topic872361-392-1.aspx
The code in question is below and performs standard gauss-jordan elimination to reduce supplied data points to an equation, then extrapolates accordingly:
-- Point type
CREATE TYPE Point AS TABLE (XCoordinate FLOAT, YCoordinate FLOAT);
GO
-- Curve fitting coefficient type
CREATE TYPE Coefficient AS TABLE (Multiplier FLOAT, PowerOfX INT);
GO
/**
* Function: fn_CurveFitPoints
* Author: Steven James Gray [ steve#cobaltsoftware.net ]
* Date: 24th February, 2010
* Version: 1.0
* Description:
* Takes a series of points in a table variant in POINT (X float, Y float) format and
* computes the n-1 power series curve fit using the Gauss-Jordan elimination process.
* Return value is a series of Multiplier, Power elements that can be used for producing
* an estimated Y value for any X value.
*
* Please refer to fn_ExtrapolateYValue(#xvalue, #coefficients) for a simple implementation
* of how to use the output of this function.
**/
CREATE FUNCTION dbo.fn_CurveFitPoints
(
#PointsToCurveFit POINT readonly
)
RETURNS #Result TABLE (Multiplier FLOAT, PowerOfX INT)
AS
BEGIN
-- ==========================================================================================
-- Stage 1 - Convert #PointsToFit into a matrix
-- ==========================================================================================
DECLARE #Matrix TABLE (MatrixRow INT, MatrixColumn INT, MatrixValue FLOAT);
DECLARE #TotalPoints INT = (SELECT COUNT(1) FROM #PointsToCurveFit);
WITH NumberProjectionCTE(CurrentNumber)
AS
(
SELECT 1
UNION ALL
SELECT 1+CurrentNumber FROM NumberProjectionCTE WHERE CurrentNumber < #TotalPoints
) INSERT INTO #Matrix
SELECT
Sequence-1, -- Each point gets it's own row
PWR.CurrentNumber-1, -- Column per power of X
CASE
WHEN PWR.CurrentNumber = 1 -- 1st column is X^0 = 1 Always
THEN 1
ELSE POWER(XCoordinate,PWR.CurrentNumber-1) -- Raise nth column to power n-1.
END
FROM
NumberProjectionCTE PWR, -- Cross join numeric point data and column indexes
(SELECT
ROW_NUMBER() OVER (ORDER BY XCoordinate, YCoordinate) AS Sequence,
XCoordinate,
YCoordinate
FROM
#PointsToCurveFit
) ValueData;
/* Append Y values as nth column */
INSERT INTO #Matrix
SELECT
ROW_NUMBER() OVER (ORDER BY XCoordinate, YCoordinate) - 1 AS Sequence,
#TotalPoints,
YCoordinate
FROM
#PointsToCurveFit;
-- ==========================================================================================
-- Stage 2 - Compute row echelon form of matrix
-- ==========================================================================================
DECLARE #lead INT = 0, #index INT = 0, #current FLOAT;
DECLARE #Rows INT = (SELECT MAX(MatrixRow) FROM #Matrix);
DECLARE #Columns INT = (SELECT MAX(MatrixColumn) FROM #Matrix);
DECLARE #Solved INT -- 0=Unsolvable, 1 = Solved
DECLARE #R INT = 0
WHILE #R <= #Rows
BEGIN
IF #Columns <= #lead
BEGIN
-- Cannot solve this one
SET #Solved = 0;
BREAK;
END;
SET #index = #R;
-- Determine if any row swaps are needed.
WHILE (SELECT MatrixValue FROM #Matrix WHERE MatrixRow = #index AND MatrixColumn = #lead) = 0
BEGIN
SET #index = #index + 1;
IF #Rows = #index
BEGIN
SET #index = #R;
SET #lead = #lead + 1;
IF #Columns = #lead
BEGIN
-- Cannot solve
SET #Solved = 0;
BREAK;
END;
END;
END;
-- Move this row to the correct position if needed.
IF #index <> #R
BEGIN
-- Swap rows
UPDATE #Matrix
SET MatrixRow = CASE MatrixRow
WHEN #R THEN #index
WHEN #index THEN #R
END
WHERE MatrixRow IN (#index, #R);
END;
-- Divide this row by it's lead column value, so that this row's lead is 1 (this will actually multiply/increase the value if lead <0)
DECLARE #Divisor FLOAT = (SELECT MatrixValue FROM #Matrix WHERE MatrixRow = #R AND MatrixColumn = #lead);
If #Divisor <> 1
BEGIN
UPDATE #Matrix SET MatrixValue = MatrixValue / #Divisor WHERE MatrixRow = #R;
END;
-- Update other rows and divide them by the appropriate multiple of this row in order to zero the current lead column.
UPDATE I
SET
MatrixValue = I.MatrixValue - (M.MatrixValue * R.MatrixValue)
FROM
#Matrix I
INNER JOIN #Matrix M ON M.MatrixRow = I.MatrixRow AND M.MatrixColumn = #lead
INNER JOIN #Matrix R ON R.MatrixColumn = I.MatrixColumn AND R.MatrixRow = #R AND R.MatrixRow <> I.MatrixRow
SET #lead = #lead + 1;
-- Move to next
SET #R = #R + 1;
END;
-- If we didn't bomb out, we're solved.
IF #Solved IS NULL
BEGIN
SET #Solved = 1
END;
-- ==========================================================================================
-- Stage 3 - Produce coefficients list (The final colum when in REF)
-- ==========================================================================================
IF #Solved = 1
BEGIN
INSERT INTO #Result (Multiplier, PowerOfX)
SELECT
MatrixValue,
MatrixRow
FROM #Matrix
WHERE MatrixColumn = #Columns;
END;
RETURN;
END;
GO
CREATE FUNCTION dbo.fn_ExtrapolateYValue
(
#XValue FLOAT,
#Coefficients Coefficient readonly
)
RETURNS FLOAT
AS
BEGIN
RETURN (SELECT SUM(Multiplier * POWER(#XValue, PowerOfX)) FROM #Coefficients);
END
For example:
DECLARE #PointsToCurveFit Point
-- A few simple X/Y values
INSERT INTO #PointsToCurveFit SELECT 1 , 6
INSERT INTO #PointsToCurveFit SELECT 2 , 3
INSERT INTO #PointsToCurveFit SELECT 3 , 2
-- Calculate the curve fitting coefficients
DECLARE #Coefficients Coefficient
INSERT INTO #Coefficients SELECT * FROM dbo.fn_CurveFitPoints(#PointsToCurveFit);
-- Shows that y= 11x^0 + 6x + x^2
SELECT * FROM #Coefficients;
-- Show the values for X=-5 to 5
WITH NumberCTE(Number)
AS
(
SELECT -5
UNION ALL
SELECT 1 + Number FROM NumberCTE WHERE Number < 5
) SELECT
Number AS XValue,
dbo.fn_ExtrapolateYValue(Number, #Coefficients) AS YValue
FROM NumberCTE;
In the code specified, I extrapolate the function of the curve from -5 to +5 on the X axis range.
I had this quest for enginering system, calucalting welding strength and here is how I solved it - clean and simple.
CREATE TABLE WeldStrengthReduction
(
[Temperature] numeric(18,4) NOT NULL ,
[Reduction] numeric(18,4) NOT NULL ,
);
GO
insert into WeldStrengthReduction (Temperature,Reduction)
values
(510,1),
(538,0.95),
(566,0.91),
(593,0.86),
(621,0.82),
(649,0.77),
(677,0.73),
(704,0.68),
(732,0.64),
(760,0.59),
(788,0.55),
(816,0.5);
Go
Create Function WSRF(#Tempreture Numeric(18,4) ) returns Numeric(18,4)
as
begin
declare
#X1 Numeric(18,4),
#X2 Numeric(18,4),
#X3 Numeric(18,4),
#Y1 Numeric(18,4),
#Y2 Numeric(18,4),
#Y3 Numeric(18,4),
#pointer int
set #X2 = #Tempreture
declare #Templist table (id int IDENTITY(1,1), temp numeric(18,4), red numeric(18,4))
insert into #Templist select Temperature,Reduction from WeldStrengthReduction order by Temperature
select top 1 #X3 = temp, #Y3 = red, #pointer = id from #Templist where temp >= #Tempreture
if #pointer = 1 return #Y3 -- if incomming tempereture is below lowest, return according to lowewst temp
if #pointer is null return null -- if incomming tempereture is above highest, return null
select #X1 = temp, #Y1 = red from #Templist where id = #pointer - 1
set #Y2 = ((#X2-#X1)*(#Y3-#Y1))/(#X3 - #X1) + #Y1
return #Y2
end;
Go
select WSRF(772);
select WSRF(300);
select WSRF(1200);

A domain error occurred in SQL Server 2000 while updating the data

I have created a function like the one below
ALTER FUNCTION fn_Calc
(#Lat1 Float,
#Lng1 Float,
#Lat2 Float,
#Lng2 Float)
RETURNS Float
AS
BEGIN
Declare #x as Float
Declare #y as Float
Declare #Distance as Float
Select #x = (SIN(RADIANS(#Lat1)) * SIN(RADIANS(#Lat2)) + COS(RADIANS(#Lat1)) * COS(RADIANS(#Lat2)) * COS(ABS((RADIANS(#Lng2)) - (RADIANS(#Lng1)))))
Select #y = ATAN((SQRT(1-(POWER(#x,2))) / #x))
Select #Distance = (1.852 * 60.0 * ((#y / PI()) * 180)) / 1.609344
RETURN #Distance
END
I am using the above function to update a column in a table like below:
Update test
set calc = dbo.fn_Calc(cast(Lat as float), cast(Long as float), dblLat, dblLong)
While running the above query I got the error.
"A domain error occured."
What can be causing this error?
Try this one -
ALTER FUNCTION dbo.fn_Calc
(
#Lat1 FLOAT
, #Lng1 FLOAT
, #Lat2 FLOAT
, #Lng2 FLOAT
)
RETURNS FLOAT
AS BEGIN
DECLARE
#x FLOAT
, #y FLOAT
SELECT #x =
SIN(RADIANS(#Lat1))
* SIN(RADIANS(#Lat2)) + COS(RADIANS(#Lat1))
* COS(RADIANS(#Lat2))
* COS(ABS(RADIANS(#Lng2) - RADIANS(#Lng1)))
SELECT #y = ATAN(SQRT(ABS(1 - POWER(#x, 2))) / #x)
RETURN (111.12 * ((#y / PI()) * 180)) / 1.609344
END

SQL Server: Finding Nearest Location

Given the following SQL which returns a list of airports based on a given city, how would I further enhance it to sort the results by what's nearest to me? It seems like it should be simple enough but it eludes me.
DECLARE #latRange float
DECLARE #LongRange float
DECLARE #LowLatitude float
DECLARE #HighLatitude float
DECLARE #LowLongitude float
DECLARE #HighLongitude float
DECLARE #Radius float = 100
DECLARE #istartlat float
DECLARE #istartlong float
Select #istartlat=Latitude, #istartlong=Longitude from Lookup where PlaceName = '"Franklin"' and StateCode = '"AR"'
Select #latRange = #Radius / ((6076 / 5280) * 60)
Select #LongRange = #Radius / (((COS((#istartlat * 3.14592653589 / 180)) * 6076.) / 5280. * 60))
Select #LowLatitude = #istartlat - #latRange
Select #HighLatitude = #istartlat + #latRange
Select #LowLongitude = #istartlong - #LongRange
Select #HighLongitude = #istartlong + #LongRange
Select a.City, a.State, a.AirportCode, a.AirportName, a.CountryCode
from PFM_Airport a
where (a.Latitude <= #HighLatitude) and (a.Latitude >= #LowLatitude) and (a.Longitude >= #LowLongitude)
and (a.Longitude <= #HighLongitude)
--and a.CountryCode in ('USA', 'CANADA')
order by a.Latitude, a.Longitude;
#hatchet is right.. Assuming your instance of SQL Server support geography spatial data then you should consider using that data type for the calculations, you also may find useful some of this code, just replace the table names, conditionals and pagination as needed:
ALTER PROCEDURE [dbo].[SP_NearestPOIReloaded]
(
-- Add the parameters for the stored procedure here
#LAT float,
#LNG float,
#DISTANCE int,
#CURRENTPAGE Int,
#PAGESIZE Int,
#COUNT int OUTPUT
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
/*for pagination*/
SET #COUNT = (SELECT COUNT(*) FROM dbo.Lugares as [L] WHERE dbo.DistanceBetween(#LAT, #LNG, [L].lat, [L].lng) < #DISTANCE)
/*paginated resultset*/
SELECT * FROM (
SELECT ROW_NUMBER()Over(Order by dbo.DistanceBetween(#LAT, #LNG, [L].lat, [L].lng) Asc) As [RowNum], dbo.DistanceBetween(#LAT, #LNG, [L].lat, [L].lng) as [distance], [L].*, [E].name as [empresaName], [U].userName as [userName]
FROM dbo.Lugares as [L], dbo.Empresas as [E], dbo.Usuarios as [U]
WHERE dbo.DistanceBetween(#LAT, #LNG, [L].lat, [L].lng) < #DISTANCE AND
[L].usuarioId = [U].id AND [L].empresaId = [E].id
)
AS ResultadoPaginado
WHERE RowNum BETWEEN (#CURRENTPAGE - 1) * #PAGESIZE + 1 AND #CURRENTPAGE * #PAGESIZE
END
this depends on a function called DistanceBetween (if your instance does not support spacial data type, then this is the part you must replace with a variation of your own code):
ALTER FUNCTION [dbo].[DistanceBetween]
(
-- Add the parameters for the function here
#PIVOTE_LAT as float,
#PIVOTE_LNG as float,
#LAT as float,
#LNG as float
)
returns real
as begin
declare #distance real;
declare #PIVOTE_POINT geography = geography::Point(#PIVOTE_LAT,#PIVOTE_LNG, 4326);
declare #POINT geography = geography::Point(#LAT,#LNG, 4326);
set #distance = #PIVOTE_POINT.STDistance(#POINT);
return (#distance);
end
how would I further enhance it to sort the results by what's nearest to me?
I believe that in SQL Server 2000, to sort on a calculated value you must either duplicate the calculation in the ORDER BY clause ORDER BY < the calculation> or you can do this:
select FOO.a, FOO.b, FOO.myvalue
from
(
select a, b, <some calculation> as myvalue
from T
where <some calculation> <= {some value}
) as FOO
order by FOO.myvalue
P.S. But in later versions of SQL you can sort on a column alias.
In any case, you must have a column to contain the calculated distance.

Incorrect syntax near the keyword 'CREATE' while creating function

I am a complete newbie when it comes to MS SQL and have found this code online while searching. It seems like it would do exactly what I want, which is do a radius search based on Latitude and Latitude values.
However, I keep getting: Incorrect syntax near the keyword 'CREATE'. , which is the very first line of the code. My database is 2008 MS SQL
Here is the code:
CREATE FUNCTION CalculateDistance
(#Longitude1 Decimal(8,5),
#Latitude1 Decimal(8,5),
#Longitude2 Decimal(8,5),
#Latitude2 Decimal(8,5))
Returns Float
AS BEGIN
Declare #Temp Float
Set #Temp = sin(#Latitude1/57.2957795130823) * sin(#Latitude2/57.2957795130823) + cos(#Latitude1/57.2957795130823) * cos(#Latitude2/57.2957795130823) * cos(#Longitude2/57.2957795130823 - #Longitude1/57.2957795130823)
if #Temp > 1
Set #Temp = 1
Else If #Temp < -1
Set #Temp = -1
Return (3958.75586574 * acos(#Temp) )
End
-- FUNCTION
CREATE FUNCTION LatitudePlusDistance(#StartLatitude Float, #Distance Float) Returns Float
AS BEGIN
Return (Select #StartLatitude + Sqrt(#Distance * #Distance / 4766.8999155991))
End
-- FUNCTION
CREATE FUNCTION LongitudePlusDistance
(#StartLongitude Float,
#StartLatitude Float,
#Distance Float)
Returns Float
AS BEGIN
Return (Select #StartLongitude + Sqrt(#Distance * #Distance / (4784.39411916406 * Cos(2 * #StartLatitude / 114.591559026165) * Cos(2 * #StartLatitude / 114.591559026165))))
End
-- ACTUAL QUERY
-- Declare some variables that we will need.
Declare #Longitude Decimal(8,5),
#Latitude Decimal(8,5),
#MinLongitude Decimal(8,5),
#MaxLongitude Decimal(8,5),
#MinLatitude Decimal(8,5),
#MaxLatitude Decimal(8,5)
-- Get the lat/long for the given id
Select #Longitude = Longitude,
#Latitude = Latitude
From qccities
Where id = '21'
-- Calculate the Max Lat/Long
Select #MaxLongitude = LongitudePlusDistance(#Longitude, #Latitude, 20),
#MaxLatitude = LatitudePlusDistance(#Latitude, 20)
-- Calculate the min lat/long
Select #MinLatitude = 2 * #Latitude - #MaxLatitude,
#MinLongitude = 2 * #Longitude - #MaxLongitude
-- The query to return all ids within a certain distance
Select id
From qccities
Where Longitude Between #MinLongitude And #MaxLongitude
And Latitude Between #MinLatitude And #MaxLatitude
And CalculateDistance(#Longitude, #Latitude, Longitude, Latitude) <= 2
Any idea what's going on?
Thank you!!!
EDIT: Thank you very much to bluefeet and Aaron Bertrand for pointing me in the right direction!
You should also end the each of create statements with a GO or semicolon:
Also, should add the schema to the function. For example the below uses the dbo. schema:
CREATE FUNCTION dbo.CalculateDistance
(#Longitude1 Decimal(8,5),
#Latitude1 Decimal(8,5),
#Longitude2 Decimal(8,5),
#Latitude2 Decimal(8,5))
Returns Float
AS BEGIN
Declare #Temp Float
Set #Temp = sin(#Latitude1/57.2957795130823) * sin(#Latitude2/57.2957795130823) + cos(#Latitude1/57.2957795130823) * cos(#Latitude2/57.2957795130823) * cos(#Longitude2/57.2957795130823 - #Longitude1/57.2957795130823)
if #Temp > 1
Set #Temp = 1
Else If #Temp < -1
Set #Temp = -1
Return (3958.75586574 * acos(#Temp) )
End
GO
See SQL Fiddle with Demo of all functions being created.
Try a single function without the GO. GO is not part of T-SQL, it is a batch separator for client tools like Management Studio. ColdFusion is probably passing that along to SQL Server and it doesn't understand the GO. So either send one function at a time from ColdFusion (without the GO), or use a better tool for creating objects and sending queries (e.g. Management Studio or whatever client interface the host provides you with).
I'm not sure why you think you need to create the three functions in a single code block instead of creating them separately (since your web page obviously has no clue about batches). You only need to create the functions once. After you have created them in the database, you can reference them in subsequent queries all day/week/month/year etc.
You have to separate multiple CREATE FUNCTION calls with GO OR ; (or both - which one I prefer):
CREATE FUNCTION CalculateDistance
(#Longitude1 Decimal(8,5),
#Latitude1 Decimal(8,5),
#Longitude2 Decimal(8,5),
#Latitude2 Decimal(8,5))
Returns Float
AS BEGIN
Declare #Temp Float
Set #Temp = sin(#Latitude1/57.2957795130823) * sin(#Latitude2/57.2957795130823) + cos(#Latitude1/57.2957795130823) * cos(#Latitude2/57.2957795130823) * cos(#Longitude2/57.2957795130823 - #Longitude1/57.2957795130823)
if #Temp > 1
Set #Temp = 1
Else If #Temp < -1
Set #Temp = -1
Return (3958.75586574 * acos(#Temp) )
End;
GO
-- FUNCTION
CREATE FUNCTION LatitudePlusDistance(#StartLatitude Float, #Distance Float) Returns Float
AS BEGIN
Return (Select #StartLatitude + Sqrt(#Distance * #Distance / 4766.8999155991))
End
-- FUNCTION
CREATE FUNCTION LongitudePlusDistance
(#StartLongitude Float,
#StartLatitude Float,
#Distance Float)
Returns Float
AS BEGIN
Return (Select #StartLongitude + Sqrt(#Distance * #Distance / (4784.39411916406 * Cos(2 * #StartLatitude / 114.591559026165) * Cos(2 * #StartLatitude / 114.591559026165))))
End;
GO
There are a number of CREATE statements in that SQL. They have to be separated into batches by putting GO between the statements.
This is revealed by the half of the message in SSMS:
'CREATE FUNCTION' must be the first statement in a query batch.
So to fix:
CREATE FUNCTION CalculateDistance
(#Longitude1 Decimal(8,5),
#Latitude1 Decimal(8,5),
#Longitude2 Decimal(8,5),
#Latitude2 Decimal(8,5))
Returns Float
AS BEGIN
...
END
GO
CREATE FUNCTION LatitudePlusDistance(#StartLatitude Float, #Distance Float) Returns Float
AS BEGIN
Return (Select #StartLatitude + Sqrt(#Distance * #Distance / 4766.8999155991))
End
GO
CREATE FUNCTION... etc

Resources