Compatible SQL function for Excel FDist - excel

Does anyone know that is there a compatible function in SQL for Excel FDIST and FINV? If there is no, anyone has any idea how to build that? May be in C#?
Thanks. Your help is greatly appreciated.

I have managed to resolve my problems by using a library from .Net Framework 4.0 and above (System.Windows.Forms.DataVisualization.Charting.StatisticFormula).
I am able to develop a function in C# using the above library for my calculation process. This is a powerful library where you can find mostly common use statistical formula in there (e.g. mean, median, t distribution, f distribution, and inverse of them.)
Below are the code snippet from me:
using System.Windows.Forms.DataVisualization.Charting;
private Chart ch = new Chart(); // You will need to declare an object of Chart type, as Statistic Formula class does not have a public constructor
double fDist = ch.DataManipulator.Statistics.FDistribution(fRatioVariance, degreeFreedom1, degreeFreedom2);
Hope this will help others. Thanks.

Though its too late but below are some statistical function implementation in SQL Server itself.
To get FDist function (equivalent to Excel - FDist), we will be needing Complete and Incomplete beta function as well as gamma function:
--GAMMA Function
CREATE FUNCTION [dbo].[udf_Gamma]
(
#x Float=NULL
)
RETURNS Float
AS
BEGIN
Declare #f Float = 10E99;
Declare #g Float = 1;
if ( #x > 0 )
Begin
while (#x < 3)
Begin
SET #g = #g * #x;
SET #x = #x + 1;
End
SET #f = (1 - (2/(7*power(#x,2))) * (1 - 2/(3*power(#x,2))))/(30*power(#x,2));
SET #f = (1-#f)/(12*#x) + #x*(log(#x)-1);
SET #f = (exp(#f)/#g)*power(2*PI()/#x,0.5);
End
else
Begin
SET #f = 10E99
End
return #f;
END
--BETA Complete Function
CREATE FUNCTION [dbo].[udf_BetaC]
(
#x Float=NULL
,#a Float=NULL
,#b Float=NULL
)
RETURNS Float
AS
BEGIN
--double betacf(double a,double b,double x){
Declare #maxIterations int = 50, #m int =1
Declare #eps Float = 3E-5
Declare #am Float = 1;
Declare #bm Float = 1;
Declare #az Float = 1;
Declare #qab Float = #a+#b;
Declare #qap Float = #a+1;
Declare #qam Float = #a-1;
Declare #bz Float = 1 - #qab*#x/#qap;
Declare #aold Float = 0;
Declare #em Float, #tem Float, #d Float, #ap Float, #bp Float, #app Float, #bpp Float;
while((#m<#maxIterations) AND (abs(#az-#aold)>=#eps*abs(#az)))
Begin
SET #em = #m;
SET #tem = #em+#em;
SET #d = #em*(#b-#m)*#x/((#qam + #tem)*(#a+#tem));
SET #ap = #az+#d*#am;
SET #bp = #bz+#d*#bm;
SET #d = -(#a+#em)*(#qab+#em)*#x/((#a+#tem)*(#qap+#tem));
SET #app = #ap+#d*#az;
SET #bpp = #bp+#d*#bz;
SET #aold = #az;
SET #am = #ap/#bpp;
SET #bm = #bp/#bpp;
SET #az = #app/#bpp;
SET #bz = 1;
SET #m = #m + 1;
End
return #az
END
--BETA INCOMPLETE Function
CREATE FUNCTION [dbo].[udf_BetaI]
(
#x Float=null
,#a Float=null
,#b Float=null
)
RETURNS Float
AS
BEGIN
Declare #bt Float=0.0
Declare #beta Float=0.0
if( #x=0 OR #x=1 )
Begin
SET #bt = 0
End
else if((#x>0) AND (#x<1))
Begin
SET #bt = (Select dbo.UDF_Gamma(#a+#b)* power(#x,#a)* power(1-#x,#b)/(dbo.UDF_Gamma(#a)*dbo.UDF_Gamma(#b)) )
End
if(#x<(#a+1)/(#a+#b+2))
Begin
SET #beta = (Select #bt*dbo.udf_betaC(#x,#a,#b)/#a)
End
else
Begin
SET #beta = (Select 1-#bt*dbo.udf_betaC(1-#x,#b,#a)/#b)
End
Return #beta
END
--FDist Function
CREATE FUNCTION [dbo].[udf_FDist]
(
#x Float=NULL
,#df1 Float=NULL
,#df2 Float=NULL
)
RETURNS Float
AS
BEGIN
Declare #x1 Float=(#x*#df1)/((#x*#df1)+#df2)
return (select 1 - dbo.udf_BetaI(#x1,(#df1/2),(#df2/2)))
END
Check in Excel =FDIST(0.5,1,1)=0.608173448
and in SQL editor = SELECT udf_FDIST(0.5,1,1)=0.608173457369209
Regards,
Avi

FDIST an FINV Don't exists IN Sql Server.
You can write a SQL Sever function to implement two excel feature.
Show here to create function

in MS SQL Server there is standard_deviation
and some more statistical functions including variance.
There is also a million workarounds, for example: http://oreilly.com/catalog/transqlcook/chapter/ch08.html
,you need to dig deep into the math for these, though.

Related

Text values in formulas are limited to 255 characters to create longer text values in formula

I want to insert some big values in an excel sheet, but it is giving errors.
Error
Text values in formulas are limited to 255 characters. To create text
values longer in a formula, use the CONCATENATE
function or the concatenation operator (&).
Value
=CONCATENATE("BEGIN TRY
BEGIN TRANSACTION
BEGIN --User defined values
DECLARE #FieldName NVARCHAR(100) = '",F2,"';
DECLARE #Currencycode VARCHAR(3) = '",A2,"';
DECLARE #Countrycode VARCHAR(2) = '",B2,"';
DECLARE #RuleType NVARCHAR(100) = 'CannotContainSpecialCharOtherThan';
DECLARE #RuleValue INT = 0;
DECLARE #InsFieldTypeDesc NVARCHAR(50) = 'AnyType';
DECLARE #RuleValueAlpha NVARCHAR(4000) = '/: (),.''-?+';
DECLARE #ErrMsg NVARCHAR(500) = '",N2,"';
DECLARE #ErrCode NVARCHAR(10) = '",M2,"';
DECLARE #ErrPrior TINYINT = '",L2,"';
DECLARE #IsLength INT = 0; ---if length is there then set this 1 or 0
DECLARE #DependantOn NVARCHAR(100) = NULL
END
BEGIN --Consts
DECLARE #UTCTime DATETIME = Getutcdate();
DECLARE #CTTime DATETIME = Dateadd(hour, -5, Getutcdate());
END
DECLARE #FieldRuleConfigPk INT;
DECLARE #ErrorMsgpk INT;
DECLARE #countryfk INT;
DECLARE #Fieldnamefk INT;
DECLARE #InsFieldTypeFk INT;
DECLARE #RuleValue1 INT = 0;
DECLARE #RuleValue2 INT = 19;
DECLARE #RuleValue3 INT = 19;
DECLARE #RuleTypeFk INT;
DECLARE #ErrorFk INT;
DECLARE #IsOk INT = 0
PRINT( 'Starts script' )
BEGIN --INIT
SET #countryfk = (SELECT countrypk
FROM mas_country
WHERE countrycode = #Countrycode);
SET #Fieldnamefk = (SELECT fieldnamepk
FROM mas_fieldname
WHERE fieldname = #FieldName);
SET #InsFieldTypeFk = (SELECT instructionfieldtypepk
FROM mas_instructionfieldtype
WHERE fieldtypedesc = #InsFieldTypeDesc);
END
IF NOT EXISTS (SELECT 1
FROM mas_fieldruleconfig
WHERE currencycode = #Currencycode
AND countryfk = #countryfk
AND fieldnamefk = #Fieldnamefk)
BEGIN
INSERT INTO mas_fieldruleconfig
(currencycode,
countryfk,
fieldnamefk,
instructionfieldtypefk,
createddateutc,
createddatect)
VALUES ( #Currencycode,
#countryfk,
#Fieldnamefk,
#InsFieldTypeFk,
#UTCTime,
#CTTime )
SELECT #FieldRuleConfigPk = Scope_identity();
SET #IsOk = 1
PRINT( 'mas_fieldruleconfig insert success' )
END
ELSE
BEGIN
SELECT #FieldRuleConfigPk = fieldruleconfigpk
FROM mas_fieldruleconfig
WHERE currencycode = #Currencycode
AND countryfk = #countryfk
AND fieldnamefk = #Fieldnamefk
PRINT( 'mas_fieldruleconfig setting already exists' )
END
IF NOT EXISTS (SELECT 1
FROM mas_ruletype
WHERE ruletype = #RuleType
AND fieldruleconfigfk = #FieldRuleConfigPk
--Need to add this check, otherwise it will fail
AND rulevalue = #RuleValue --Not needed
AND rulevaluealphanumeric = #RuleValueAlpha)
--Not needed
BEGIN
INSERT INTO mas_ruletype
(ruletype,
fieldruleconfigfk,
rulevalue,
rulevaluealphanumeric,
createddateutc,
createddatect,
dependanton)
VALUES ( #RuleType,
#FieldRuleConfigPk,
#RuleValue,
#RuleValueAlpha,
#UTCTime,
#CTTime,
#DependantOn)
SELECT #RuleTypeFk = Scope_identity();
SET #IsOk = 1
PRINT( 'mas_ruletype insert success' )
END
ELSE
BEGIN
SELECT #RuleTypeFk = (SELECT ruletypepk
FROM mas_ruletype
WHERE ruletype = #RuleType
AND fieldruleconfigfk =
#FieldRuleConfigPk
--Need to add this check, otherwise it will fail
AND rulevalue = #RuleValue
--Not needed
AND rulevaluealphanumeric =
#RuleValueAlpha)
PRINT( 'mas_ruletype settings already exists' )
END
IF NOT EXISTS (SELECT 1
FROM mas_errormessage
WHERE errormessage = #ErrMsg)
BEGIN
INSERT INTO mas_errormessage
(errormessage,
createddateutc,
createddatect)
VALUES ( #ErrMsg,
#UTCTime,
#CTTime )
SELECT #ErrorMsgpk = Scope_identity()
SET #IsOk = 1
PRINT( 'mas_errmsg insert success' )
END
ELSE
BEGIN
SELECT #ErrorMsgpk = errormessagepk
FROM mas_errormessage
WHERE errormessage = #ErrMsg
PRINT( 'mas_errormsg settings already exists' )
END
IF NOT EXISTS (SELECT 1
FROM mas_error
WHERE fieldnamefk = #Fieldnamefk
AND errorcode = #ErrCode)
BEGIN
INSERT INTO mas_error
(fieldnamefk,
errorcode,
errorpriority,
errormessagefk,
createddateutc,
createddatect)
VALUES ( #Fieldnamefk,
#ErrCode,
#ErrPrior,
#ErrorMsgpk,
#UTCTime,
#CTTime )
SELECT #ErrorFk = Scope_identity();
SET #IsOk = 1
PRINT( 'mas_error insert success' )
END
ELSE
BEGIN
SELECT #ErrorFk = (SELECT errorpk
FROM mas_error
WHERE fieldnamefk = #Fieldnamefk
AND errorcode = #ErrCode);
PRINT( 'Mas_Error settings already exists' )
END
IF NOT EXISTS (SELECT 1
FROM [lnk_fieldruleerror]
WHERE [fieldruleconfigfk] = #FieldRuleConfigPk
AND [fieldnamefk] = #Fieldnamefk
AND [ruletypefk] = #RuleTypeFk
AND #ErrorFk = #ErrorFk)
BEGIN
INSERT INTO [dbo].[lnk_fieldruleerror]
([fieldruleconfigfk],
[fieldnamefk],
[ruletypefk],
[errorfk])
VALUES (#FieldRuleConfigPk,
#Fieldnamefk,
#RuleTypeFk,
#ErrorFk)
END
IF #IsOk = 1
BEGIN
COMMIT TRANSACTION
PRINT( 'commit' )
END
END TRY
BEGIN CATCH
PRINT 'Error'
PRINT ( 'Rollback' )
ROLLBACK TRANSACTION;
END CATCH")
I have followed this link also but could not find a solution.
Try breaking it up like this:
=CONCATENATE("BEGIN TRY",CHAR(10),
"BEGIN TRANSACTION",CHAR(10),
"dgd",CHAR(10),
"dfh",CHAR(10),
etc.
);
I have solved by splitting the value into multiple cells and merging these into a new cell like this =A2&" "&B2

SAS simplify the contents of a variable

In SAS, I've a variable V containing the following value
V=1996199619961996200120012001
I'ld like to create these 2 variables
V1=19962001 (= different modalities)
V2=42 (= the first modality appears 4 times and the second one appears 2 times)
Any idea ?
Thanks for your help.
Luc
For your first question (if I understand the pattern correctly), you could extract the first four characters and the last four characters:
a = substr(variable, 1,4)
b = substrn(variable,max(1,length(variable)-3),4);
You could then concatenate the two.
c = cats(a,b)
For the second, the COUNT function can be used to count occurrences of a string within a string:
http://support.sas.com/documentation/cdl/en/lefunctionsref/63354/HTML/default/viewer.htm#p02vuhb5ijuirbn1p7azkyianjd8.htm
Hope this helps :)
Make it a bit more general;
%let modeLength = 4;
%let maxOccur = 100; ** in the input **;
%let maxModes = 10; ** in the output **;
Where does a certain occurrence start?;
%macro occurStart(occurNo);
&modeLength.*&occurNo.-%eval(&modeLength.-1)
%mend;
Read the input;
data simplified ;
infile datalines truncover;
input v $%eval(&modeLength.*&maxOccur.).;
Declare output and work variables;
format what $&modeLength..
v1 $%eval(&modeLength.*&maxModes.).
v2 $&maxModes..;
array w {&maxModes.}; ** what **;
array c {&maxModes.}; ** count **;
Discover unique modes and count them;
countW = 0;
do vNo = 1 to length(v)/&modeLength.;
what = substr(v, %occurStart(vNo), &modeLength.);
do wNo = 1 to countW;
if what eq w(wNo) then do;
c(wNo) = c(wNo) + 1;
goto foundIt;
end;
end;
countW = countW + 1;
w(countW) = what;
c(countW) = 1;
foundIt:
end;
Report results in v1 and v2;
do wNo = 1 to countW;
substr(v1, %occurStart(wNo), &modeLength.) = w(wNo);
substr(v2, wNo, 1) = put(c(wNo),1.);
put _N_= v1= v2=;
end;
keep v1 v2;
The data I testes with;
datalines;
1996199619961996200120012001
197019801990
20011996199619961996200120012001
;
run;

How to calculate integral, numerically, in Rcpp

I've searched for an hour for the methods doing numerical integration. I'm new to Rcpp and rewriting my old programs now. What I have done in R was:
x=smpl.x(n,theta.true)
joint=function(theta){# the joint dist for
#all random variable
d=c()
for(i in 1:n){
d[i]=den(x[i],theta)
}
return(prod(d)*dbeta(theta,a,b)) }
joint.vec=Vectorize(joint)##vectorize the function, as required when
##using integrate()
margin=integrate(joint.vec,0,1)$value # the
##normalizeing constant at the donominator
area=integrate(joint.vec,0,theta.true)$value # the values at the
## numeritor
The integrate() function in R will be slow, and since I am doing the integration for a posterior distribution of a sample of size n, the value of the integration will be huge with large error.
I am trying to rewrite my code with the help of Rcpp, but I don't know how to deal with the integrate. Should I include a c++ h file? Or any suggestions?
You can code your function in C and call it, for instance, via the sourceCpp function and then integrate it in R. In alternative, you can call the integrate function of R within your C code by using the Function macro of Rcpp. See Dirk's book (Seamless R and C++ Integration with Rcpp) on page 56 for an example of how to call R functions from C. Another alternative (which I believe is the best for most cases) is to integrate your function written in C , directly in C, using the RcppGSL package.
As about the huge normalizing constant, sometimes it is better to scale the function at the mode before integrating it (you can find modes with, e.g., nlminb, optim, etc.). Then, you integrate the rescaled function and to recover the original nroming constant multiply the resulting normalizing constant by the rescaling factor. Hope this may help!
after reading your #utobi advice, I felt programming by my own maybe easier. I simply use Simpson formula to approximate the integral:
// [[Rcpp::export]]
double den_cpp (double x, double theta){
return(2*x/theta*(x<=theta)+2*(1-x)/(1-theta)*(theta<x));
}
// [[Rcpp::export]]
double joint_cpp ( double theta,int n,NumericVector x, double a, double b){
double val = 1.0;
NumericVector d(n);
for (int i = 0; i < n; i++){
double tmp = den_cpp(x[i],theta);
val = val*tmp;
}
val=val*R::dbeta(theta,a,b,0);
return(val);
}
// [[Rcpp::export]]
List Cov_rate_raw ( double theta_true, int n, double a, double b,NumericVector x){
//This function is used to test, not used in the fanal one
int steps = 1000;
double s = 0;
double start = 1.0e-4;
std::cout<<start<<" ";
double end = 1-start;
std::cout<<end<<" ";
double h = (end-start)/steps;
std::cout<<"1st h ="<<h<<" ";
double area = 0;
double margin = 0;
for (int i = 0; i < steps ; i++){
double at_x = start+h*i;
double f_val = (joint_cpp(at_x,n,x,a,b)+4*joint_cpp(at_x+h/2,n,x,a,b)+joint_cpp(at_x+h,n,x,a,b))/6;
s = s + f_val;
}
margin = h*s;
s=0;
h=(theta_true-start)/steps;
std::cout<<"2nd h ="<<h<<" ";
for (int i = 0; i < steps ; i++){
double at_x = start+h*i;
double f_val = (joint_cpp(at_x,n,x,a,b)+4*joint_cpp(at_x+h/2,n,x,a,b)+joint_cpp(at_x+h,n,x,a,b))/6;
s = s + f_val;
}
area = h * s;
double r = area/margin;
int cover = (r>=0.025)&&(r<=0.975);
List ret;
ret["s"] = s;
ret["margin"] = margin;
ret["area"] = area;
ret["ratio"] = r;
ret["if_cover"] = cover;
return(ret);
}
I'm not that good at c++, so the two for loops like kind of silly.
It generally works, but there are still several potential problems:
I don't really know how to choose the steps, or how many sub intervals do I need to approximate the integrals. I've taken numerical analysis when I was an undergraduate, I think maybe I need to check my book about the expression of the error term, to decide the step length.
I compared my results with those from R. the integrate() function in R can take care of the integral over the interval [0,1]. That helps me because my function is undefined at 0 or 1, which takes infinite value. In my C++ code, I can only make my interval from [1e-4, 1-1e-4]. I tried different values like 1e-7, 1e-10, however, 1e-4 was the one most close to R's results....What should I do with it?

How to continuously read from the serial port in Matlab?

This is my code:
serialPort = 'COM3';
s = serial(serialPort,'BaudRate',9600);
if (s.Status == 'closed')
s.BytesAvailableFcnMode = 'byte';
s.BytesAvailableFcnCount = 200;
s.BytesAvailableFcn = #Serial_OnDataReceived;
fopen(s);
end
This is the CallBack function
function Serial_OnDataReceived(obj,event)
global s;
global i;
global endCheck;
global yVals;
global xVals;
if (s.Status == 'open')
while s.BytesAvailable > 0 && endCheck ~= '1',
data = str2num(fgetl(s));
dlmwrite ('SensorsReading.csv', data, '-append');
yVals = circshift(yVals,-1);
yVals(end) = data(3);
xVals = circshift(xVals,-1);
i = i + 0.0125;
xVals(end) = i;
end
figure(1);
plot(xVals,yVals);
end
end
Right after the FOPEN function, I get this Warning:
The BytesAvailableFcn is being disabled. To enable the callback property
either connect to the hardware with FOPEN or set the BytesAvailableFcn property.
Does the logic that happens in the callback function Serial_OnDataReceived run on a different thread?
Is there a way to pass parameters to the function? I want to modify an array in the main script from the callback function, which is in a different file. What's the best way to do so?
I am also trying to plot the values when they're updated to show some kind of dynamic animation.
I am not sure about what is generating the warning, but to answer your other question (how to pass parameter to the callback and how to update the plot), a better way to go would be to prepare your plot outside of the callback, then pass the handle to the callback for update only.
nPointsInFigure = 10 ; %// number of "sliding points" in your figure
step = 0.0125 ; %// X points spacing
xVals = linspace(-(nPointsInFigure-1)*step,0,nPointsInFigure) ; %// prepare empty data for the plot
yVals = NaN(nPointsInFigure,1) ;
figure(1) ;
hp = plot( xVals , yVals ) ; %// Generate the plot (with empty data) it will be passed to the callback.
serialPort = 'COM3';
s = serial(serialPort,'BaudRate',9600);
if (s.Status == 'closed')
s.BytesAvailableFcnMode = 'byte';
s.BytesAvailableFcnCount = 200;
s.BytesAvailableFcn = {#Serial_OnDataReceived,hp,step} ; %// note how the parameters are passed to the callback
fopen(s);
end
Your callback will become:
function Serial_OnDataReceived(obj,event,hp,step)
global endCheck; %// I don't know how you use that so I could not get rid of it.
xVals = get(hp,'XData') ; %// retrieve the X values from the plot
yVals = get(hp,'YData') ; %// retrieve the Y values from the plot
while obj.BytesAvailable > 0 && endCheck ~= '1',
data = str2num(fgetl(s));
dlmwrite ('SensorsReading.csv', data, '-append');
yVals = circshift(yVals,-1);
yVals(end) = data(3);
xVals = circshift(xVals,-1);
xVals(end) = xVals(end-1) + step ;
end
set( hp , 'XData',xVals , 'YData',yVals ) ; %// update the plot with the new values
Also note: (1) You don't need to check for the state open/close of the serial port within the callback function. If the event was triggered it means the port was open. (2) you don't need to declare s as global, the obj parameter is actually the serial object itself.
If the suggestion from Hoki does not work, try using a timer.
% The following line is useful for debugging
mytimerCallback = #(~, ~) disp('Caught error For Tenzo Timer');
if isempty(timerXbee)
timerXbee = timer('ExecutionMode','FixedRate','Period',0.1,...
'TimerFcn',{#storeDataFromSerial},'ErrorFcn', mytimerCallback);
try
start(timerXbee);
catch
disp('Timer Xbee');
disp '******** InstrumentSubscription ERROR *********'
disp (exception.message);
disp '***********************************************'
end
end
% If you are using a polling approach, request data
sendRequest(cmd);
connectionRequested = true;
Then implement the timer function that will be called every period
function storeDataFromSerial(~,~,~)
while (get(xbee, 'BytesAvailable')~=0)
serialProtocol();
end
end
When you want to disconnect the device and close the communication don't forget to stop the timer with
stop(timerXbee)

Transliteration and fuzzy search, like Google suggestions

I need to do a fuzzy search with transliteration of the characters, for example:
I have an ASP.NET application, database, which has a table with a list of Spanish words (200,000 entries), I also have a page with an input field. The point is that I do not know Spanish, and I do not know how to spell a search word in Spanish, but I know how it sounds. Therefore, in the text box I enter the search word, such as "beautiful", but in the recording err - "prekieso", and I need to get from the database got the correct version: "precioso".
How can this be implemented? In other words, I need something similar to Google suggestions...
I think what you need here is a spell checking functionality like this one: http://www.codeproject.com/KB/string/netspell.aspx
A google like functionality it's much more advanced though and will not be easy to implement:
How does the Google "Did you mean?" Algorithm work?
hope this help.
The stored procedure / function, the algorithm calculates the distance Levenshtein:
USE [**dbname**]
GO
/****** Object: UserDefinedFunction [dbo].[levenshtein] Script Date: 05/27/2013 17:54:05 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[levenshtein](#left varchar(100), #right varchar(100))
returns int
as
BEGIN
DECLARE #difference int, #lenRight int, #lenLeft int, #leftIndex int, #rightIndex int, #left_char char(1), #right_char char(1), #compareLength int
SET #lenLeft = LEN(#left)
SET #lenRight = LEN(#right)
SET #difference = 0
If #lenLeft = 0
BEGIN
SET #difference = #lenRight GOTO done
END
If #lenRight = 0
BEGIN
SET #difference = #lenLeft
GOTO done
END
GOTO comparison
comparison:
IF (#lenLeft >= #lenRight)
SET #compareLength = #lenLeft
Else
SET #compareLength = #lenRight
SET #rightIndex = 1
SET #leftIndex = 1
WHILE #leftIndex <= #compareLength
BEGIN
SET #left_char = substring(#left, #leftIndex, 1)
SET #right_char = substring(#right, #rightIndex, 1)
IF #left_char <> #right_char
BEGIN -- Would an insertion make them re-align?
IF(#left_char = substring(#right, #rightIndex+1, 1))
SET #rightIndex = #rightIndex + 1
-- Would an deletion make them re-align?
ELSE
IF(substring(#left, #leftIndex+1, 1) = #right_char)
SET #leftIndex = #leftIndex + 1
SET #difference = #difference + 1
END
SET #leftIndex = #leftIndex + 1
SET #rightIndex = #rightIndex + 1
END
GOTO done
done:
RETURN #difference
END
invoking:
select
dbo.edit_distance('Fuzzy String Match','fuzzy string match'),
dbo.edit_distance('fuzzy','fuzy'),
dbo.edit_distance('Fuzzy String Match','fuzy string match'),
dbo.edit_distance('levenshtein distance sql','levenshtein sql server'),
dbo.edit_distance('distance','server')
or:
SELECT [Name]
FR OM [tempdb].[dbo].[Names]
WHERE dbo.edit_distance([Name],'bozhestvennia') <= 3

Resources