Knowing the Value or Result on each variable SQL stored procedure - sql

This is my stored procedure:
CREATE PROCEDURE _spCalc
(#Num01 decimal(18,0), #Num02 decimal(18,0), #Num03 decimal(18,0))
AS
BEGIN
DECLARE #Var01 float, DECLARE #Var02 float, DECLARE #Var03 float
SET #Var01 = #Num01 * 1000
SET #Var02 = #Num02 - ((POWER(6.53 * #Var01, 0.5)) / (POWER(#Num03, 0.5)))
SET #Var03 = (1 - 3.4680733 * LOG(#Var02) + 1.8779192 * POWER(LOG(#Var02), 2))
INSERT INTO _myTable(Num01, Num02, Num03, Num04)
VALUES (#Num01, #Num02, #Num03, ((#Var02 + #Var03 + #Num01) * 1000))
END
My question is, how can I test and know the result of each variable that I declared? I want to compare the result with the calculation on excel format. Just want to make sure, the result is the same.
Cheers,

we can use "print #var01". repeat for different variable names before or after calculation.this shows up in messages section of results.
or
we can use " select #var01 as var01,#var02 as var02,#var03 as var03" before your insert statement.this gives you a table like output during execution
you can extend the print or select with other variables as needed.

I could not add further comments for some reasons.
"try the calculations as separate "select" before assigning to variable"
select #Num01 * 1000 as #Var01
select #Num02 - ((POWER(6.53 * #Var01, 0.5)) / (POWER(#Num03, 0.5))) as #Var02
select (1 - 3.4680733 * LOG(#Var02) + 1.8779192 * POWER(LOG(#Var02), 2))
substitute the values that u pass to the procedure accordingly

Related

How to insert the result in the desired row? SQL Server

I need the result that I got to be inserted in the right row.
DECLARE #DiscPrice float;
SET #DiscPrice = (SELECT Prod.priceProd - Prod.priceProd / 100 * Prod.disc
FROM Prod
WHERE id_prod = 1);
UPDATE Prod
SET priceDisc = #DiscPrice
WHERE id_prod = 1;
SELECT * FROM Prod;
That is, instead of WHERE id_prod = 1, there was something that inserted the desired result in all rows.
I'm not sure I made myself clear, but I hope that you will understand.
I think you want
UPDATE Prod
SET priceDisc = ((priceProd - priceProd) / 100) * disc
WHERE id_prod = 1;
There is no need to use a variable or a query to assign the value to it.
You can directly update the query as below
UPDATE Prod SET priceDisc =((priceProd - priceProd) / 100 * disc)
This will update the data in all rows

SQL Server 2008 math fail

After hunting around on various forums for almost an hour, I've come to the conclusion that SQL server is slightly stupid about simple arithmetic.
I am attempting to utilize a function which, until recently seemed to work just fine. Upon changing out some of the values for a different set of information on the form in use, I get the odd behavior ahead.
The problem is that it is giving me the incorrect result as based on an excel spreadsheet formula.
The formula looks like this:
=IF(D8=0,0,(((D8*C12-C16)*(100-C13)/100+C16)/D8)+(C18*D8))
My SQL looks like this:
(((#DaysBilled * #ContractRate - #ActualPlanDed) * (100 - #InsCover) / 100 + #ActualPlanDed) / #DaysBilled) + (#CoPay * #DaysBilled)
Filling the variables with the given data looks like this:
(((11 * 433 - 15) * (100 - 344) / 100 + 15) / 11) + (15 * 11)
Even stranger, if I use the numbers above (adding .00 to the end of each value) manually in the server environment, it gives me -11405.1200000000
With the values I am giving, it should come out 166.36. Unfortunately, I am getting -886.83
Here is the entire function and how it is called:
ALTER FUNCTION Liability
(
#ClientGUID CHAR(32),
#RecordGUID CHAR(32),
#Type CHAR(3)
)
RETURNS DECIMAL(18,2) AS
BEGIN
DECLARE #ReturnValue decimal(18,2);
DECLARE #DaysBilled int;
DECLARE #ContractRate decimal(18,2);
DECLARE #ActualPlanDed decimal(18,2);
DECLARE #InsCover decimal(18,2);
DECLARE #CoPay decimal(18,2);
IF (#Type = 'RTC')
BEGIN
SELECT #DaysBilled = RTCDaysBilled,
#ContractRate = CAST(REPLACE(REPLACE(ContractRateRTC, ' ',''),'$', '') AS DECIMAL(6,2)),
#ActualPlanDed = RTCActualPlanDed,
#InsCover = InsRTCCover,
#CoPay = RTCCoPay
FROM AccountReconciliation1
WHERE #ClientGUID = tr_42b478f615484162b2391ef0b2c35ddc
AND #RecordGUID = tr_abb4effa0d9c4fe98c78cb4d2e21ba5d
END
IF (#Type = 'PHP')
BEGIN
SELECT #DaysBilled = PHPDaysBilled,
#ContractRate = CAST(REPLACE(REPLACE(ContractRatePHP, ' ',''),'$', '') AS DECIMAL(6,2)),
#ActualPlanDed = PHPActualPlanDed,
#InsCover = InsPHPCover,
#CoPay = PHPCoPay
FROM AccountReconciliation1
WHERE #ClientGUID = tr_42b478f615484162b2391ef0b2c35ddc
AND #RecordGUID = tr_abb4effa0d9c4fe98c78cb4d2e21ba5d
END
IF (#Type = 'IOP')
BEGIN
SELECT #DaysBilled = IOPDaysBilled,
#ContractRate = CAST(REPLACE(REPLACE(ContractRateIOP, ' ',''),'$', '') AS DECIMAL(6,2)),
#ActualPlanDed = IOPActualPlanDed,
#InsCover = InsIOPCover,
#CoPay = IOPCoPay
FROM AccountReconciliation1
WHERE #ClientGUID = tr_42b478f615484162b2391ef0b2c35ddc
AND #RecordGUID = tr_abb4effa0d9c4fe98c78cb4d2e21ba5d
END
IF (#DaysBilled <> 0)
BEGIN
SET #ReturnValue = (((#DaysBilled * #ContractRate - #ActualPlanDed)
*
(100 - #InsCover) / 100 + #ActualPlanDed)
/
#DaysBilled
)
+
(#CoPay * #DaysBilled)
END
ELSE
BEGIN
SET #ReturnValue = 0;
END
RETURN #ReturnValue;
END
It is called by running a select statement from our front-end, but the result is the same as calling the function from within management studio:
SELECT dbo.Liability('ClientID','RecordID','PHP') AS Liability
I have been reading about how a unary minus tends to break SQL's math handling, but I'm not entirely sure how to counteract it.
One last stupid trick with this function: It must remain a function. I cannot convert it into a stored procedure because it must be used with our front-end, which cannot utilize stored procedures.
Does SQL server even care about the parentheses? Or is it just ignoring them?
The calculation is correct, it differes of course if you are using float values
instead of integers.
For (((11 * 433 - 15) * (100 - 344) / 100 + 15) / 11) + (15 * 11)
a value around -886.xx depending in which places integers/floats are used is correct,
What makes you believe it should be 166.36?

Extra parenthesis changing result of formula in SQL Server 2008

In all other languages (arithmetic engines in general) putting an extra set of parenthesis around operators of same priority does not impact results. But recently in a testing project I noticed that MS SQL server changes the results in those cases. Please take a look at the query below, and let me know if you have any idea (or a setting in SQL Server administration) or any links to MSDN article explaining the behavior.
select (0.55 * 287.61 / 0.66) calc_no_parens
,(0.55 * (287.61 / 0.66)) calc_parens
,round(0.55 * 287.61 / 0.66,2) no_paren_round
,round(0.55 * (287.61 / 0.66),2) paren_round;
Results
Column Record 1
calc_no_parens 239.6750000
calc_parens 239.67499985
no_paren_round 239.6800000
paren_round 239.67000000
To me, first two of them should return 239.675, and round should give 239.68.
You will get the desired result if you declare each value as Float.
DECLARE #Float1 float, #Float2 float, #Float3 float;
SET #Float1 = 0.55;
SET #Float2 = 287.61;
SET #Float3 = 0.66;
select (#Float1 * #Float2 / #Float3) calc_no_parens
,(#Float1* (#Float2/ #Float3)) calc_parens
,round(#Float1 * #Float2/ #Float3,2) no_paren_round
,round(#Float1* (#Float2/ #Float3),2) paren_round;
Output
calc_no_parens calc_parens no_paren_round paren_round
239.675 239.675 239.68 239.68
You may want to see this article: So-called "exact" numerics are not at all exact!
I can see what is happening, but I don't think there is a fix.
SQL calculates and stores each part of the function as a SQL data type (in this case it's a floating point number).
287.61/0.66 produces 435.7727272727272727272727272... which SQL will store as a floating point number to some degree of accuracy, however it isn't exact (after all, it's a floating point number).
For more info on floating point numbers: How is floating point stored? When does it matter?
Habib's answer made me thinking this has to be with decimal data types my columns are using. After a bit of research, I found this
Precision, Scale, and Length (Transact-SQL)
As you can see in that article, division operation significantly changes the both scale and precision of resulting decimal. Then I tried an variation of my query, this time adding extra parenthesis around Multiplication operation.
select distinct (0.55 * 287.61 / 0.66) calc_no_parens
,(0.55 * (287.61 / 0.66)) calc_parens_div
,((0.55 * 287.61) / 0.66) calc_parens_mult
,round(0.55 * 287.61 / 0.66,2) no_paren_round
,round(0.55 * (287.61 / 0.66),2) paren_round
,round((0.55 * 287.61) / 0.66,2) paren_round2;
Results
Column Record 1
calc_no_parens 239.6750000
calc_parens_div 239.67499985
calc_parens_mult 239.6750000
no_paren_round 239.6800000
paren_round 239.67000000
paren_round2 239.6800000
So as long as division is the last operator in the formula we get correct answers. Its not a fix to the problem, but a learning to self in any future testing projects.
When you use numbers SQL try to convert them dynamically:
{
SELECT
0.55*(287.61 / 0.66) PrecisionError,
0.55* (CONVERT(NUMERIC(24,12), 287.61) / CONVERT(NUMERIC(24,12), 0.66)) NotPrecisionError
DECLARE #V SQL_VARIANT
SET #V = 0.55*(287.61 / 0.66)
SELECT
Value = #V
,[TYPE] = CONVERT(SYSNAME, sql_variant_property(#V, 'BaseType')) + '(' +
CONVERT(VARCHAR(10), sql_variant_property(#V, 'Precision')) + ',' +
CONVERT(VARCHAR(10), sql_variant_property(#V, 'Scale')) + ')'
SET #V = 0.55 * (CONVERT(NUMERIC(24,14), 287.61) / CONVERT(NUMERIC(24,14), 0.66))
SELECT
Value = #V
,[TYPE] = CONVERT(SYSNAME, sql_variant_property(#V, 'BaseType')) + '(' +
CONVERT(VARCHAR(10), sql_variant_property(#V, 'Precision')) + ',' +
CONVERT(VARCHAR(10), sql_variant_property(#V, 'Scale')) + ')'
}
RESULTS
PrecisionError NotPrecisionError
239.67499985 239.6750000000000
Value TYPE
239.67499985 numeric(14,8)
Value TYPE
239.6750000000000 numeric(38,13)

Error converting data type varchar to numeric CAST not working

I know this has been beaten like a dead horse. However no matter how I slice it, cast it or convert it I have the same issue.
Error converting data type varchar to numeric.
SELECT property_id, property_case_number, property_address, property_city,
property_state, property_zip, property_lon, property_lat
FROM property
WHERE (property_active = 1)
AND
(property_county = (SELECT property_county FROM property AS property_1
WHERE (property_id = 9165)))
AND
(property_id <> 9165)
AND
property_lon IS NOT Null
AND
property_lat IS NOT Null
AND
dbo.LatLonRadiusDistance(
CONVERT(DECIMAL(15,12),(select property_lat from property where property_id = 9165)),
CONVERT(DECIMAL(15,12),(select property_lon from property where property_id = 9165)),
property_lat,property_lon) <= '5'
I run into this issue as soon as I add dbo.LatLonRadiusDistance at the end.
dbo.LatLonRadiusDistance compares lat & lon distance in miles.
FUNCTION [dbo].[LatLonRadiusDistance]
(
#lat1Degrees decimal(15,12),
#lon1Degrees decimal(15,12),
#lat2Degrees decimal(15,12),
#lon2Degrees decimal(15,12)
)
RETURNS decimal(9,4)
AS
BEGIN
DECLARE #earthSphereRadiusKilometers as decimal(10,6)
DECLARE #kilometerConversionToMilesFactor as decimal(7,6)
SELECT #earthSphereRadiusKilometers = 6366.707019
SELECT #kilometerConversionToMilesFactor = .621371
-- convert degrees to radians
DECLARE #lat1Radians decimal(15,12)
DECLARE #lon1Radians decimal(15,12)
DECLARE #lat2Radians decimal(15,12)
DECLARE #lon2Radians decimal(15,12)
SELECT #lat1Radians = (#lat1Degrees / 180) * PI()
SELECT #lon1Radians = (#lon1Degrees / 180) * PI()
SELECT #lat2Radians = (#lat2Degrees / 180) * PI()
SELECT #lon2Radians = (#lon2Degrees / 180) * PI()
-- formula for distance from [lat1,lon1] to [lat2,lon2]
RETURN ROUND(2 * ASIN(SQRT(POWER(SIN((#lat1Radians - #lat2Radians) / 2) ,2)
+ COS(#lat1Radians) * COS(#lat2Radians) * POWER(SIN((#lon1Radians - #lon2Radians) / 2), 2)))
* (#earthSphereRadiusKilometers * #kilometerConversionToMilesFactor), 4)
END
I'm sure it's something to do with
(select property_lat from property where property_id = 9165)
But no matter how I cast or convert it doesn't change things.
And if I run the function by itself it doesn't give an error.
Anyone have any insights?
here is a sample row
8462 023-125514 15886 W MOHAVE ST GOODYEAR AZ 85338-0000 -112.400297000000 33.429041000000
property_lat & property_lon are varchar(50)
Most likely you are expecting boolean short circuit to rescue the order of evaluating your WHERE clause. This is a known fallacy: boolean operator short circuit is not guaranteed in SQL. See On SQL Server boolean operator short-circuit for a discussion and proof that boolean short circuit can be skipped by query optimizer. Similar topic is T-SQL functions do no imply a certain order of execution. The gist of it is that SQL is a declarative language, not an imperative one.
In your case probably your cast and converts will be called for properties with IDs different from property_id = 9165 and property_active=1 and may attempt to cast string values that are not numerics to a numeric, hence the exception you see. Is difficult to give a precise diagnosis since so much information is missing from your problem description (like the exact definition of all object involved, including all tables, indexes, column types etc).
Your best avenue is to upgrade to SQL Server 2008 and use the built in geography type which has built-in support for STDistance:
This is a close approximate to the geodesic distance. The deviation of
STDistance() on common earth models from the exact geodesic distance
is no more than .25%.
After playing with the query I got it working.
SELECT [property_id], [property_case_number], [property_address], [property_city],
[property_state], [property_zip], [property_lon],
[property_lat]
FROM property
WHERE ([property_active] = 1)
AND
([property_county] = (SELECT b.property_county FROM property b WHERE (b.property_id = #prop_id)))
AND
([property_id] <> #prop_id)
AND
[property_lon] IS NOT Null
AND
[property_lat] IS NOT Null
AND
dbo.LatLonRadiusDistance(
(SELECT c.property_lat FROM property c WHERE (c.property_id = #prop_id)),
(SELECT d.property_lon FROM property d WHERE (d.property_id = #prop_id)),
CAST([property_lat] as FLOAT),
CAST([property_lon] as FLOAT)) <= 5
adding the [] seems to have skirted the issue I was having.

Haversine query into Oracle

I'm currently having to go through my queries and transfer them over to using Oracle rather than SQLSERVER and i'm a bit stuck with this query which i'm using from here
SELECT TOP 1 * FROM ( SELECT o.outcode AS lead_postcode, v.location,
v.location_name, v.outcode AS venue_postcode, 6371.0E *
( 2.0E *asin(case when 1.0E < (sqrt(square(sin(((RADIANS(CAST(o.lat AS FLOAT)))-
(RADIANS(CAST(v.lat AS FLOAT))))/2.0E)) + (cos(RADIANS(CAST(v.lat AS FLOAT)))
* cos(RADIANS(CAST(o.lat AS FLOAT))) * square(sin(((RADIANS(CAST(o.lng AS FLOAT)))-
(RADIANS(CAST(v.lng AS FLOAT))))/2.0E))))) then 1.0E else
(sqrt(square(sin(((RADIANS(CAST(o.lat AS FLOAT)))-(RADIANS(CAST(v.lat AS FLOAT))))
/2.0E)) + (cos(RADIANS(CAST(v.lat AS FLOAT))) * cos(RADIANS(CAST(o.lat AS FLOAT)))
* square(sin(((RADIANS(CAST(o.lng AS FLOAT)))-(RADIANS(CAST(v.lng AS FLOAT))))
/2.0E))))) end )) AS distance FROM venue_postcodes v, uk_postcodes o
WHERE o.outcode = #nrpostcode ) i WHERE distance<100 ORDER BY distance
Now I know this is a horrible query to look at but Oracle seems to be having a lot of problems with it.
Firstly it doesn't like the E in 6371E and all the subsequent E's
Secondly it doesn't like the square function so I decided to use the power function but this still gave me errors.
Thirdly it doesn't like the radians function
Fourthly it doesn't like the TOP 1 part so I had changed this to use ROWNUM in the WHERE clause
I'm completely lost as to what to do here.
Any ideas as to what I can do to make it work?
Thanks in advance
I'd recommend you take a slightly different approach.
Check out this site: http://psoug.org/reference/functions.html
Look for the part referring to "calc distance"
I know how to do it in SQL Server, which should be easy enough to port over to Oracle:
Here's a UDF I created to get the approximate crows flight distance between two zip codes using the Haversine formula:
ALTER FUNCTION [dbo].[fn_GetZipDistanceMiles](
#ZipFrom VARCHAR(20),
#ZipTo VARCHAR(20)
)
RETURNS FLOAT
AS
BEGIN
DECLARE #Latitude1 FLOAT
DECLARE #Longitude1 FLOAT
DECLARE #Latitude2 FLOAT
DECLARE #Longitude2 FLOAT
SELECT #Latitude1 = Latitude,
#Longitude1 = Longitude
FROM ZipCode
WHERE ZipCode = #ZipFrom
SELECT #Latitude2 = Latitude,
#Longitude2 = Longitude
FROM ZipCode
WHERE ZipCode = #ZipTo
-- CONSTANTS
DECLARE #EarthRadiusInMiles FLOAT
SET #EarthRadiusInMiles = 3963.1
-- RADIANS conversion
DECLARE #Lat1Radians FLOAT
DECLARE #Long1Radians FLOAT
DECLARE #Lat2Radians FLOAT
DECLARE #Long2Radians FLOAT
SET #Lat1Radians = #Latitude1 * PI() / 180
SET #Long1Radians = #Longitude1 * PI() / 180
SET #Lat2Radians = #Latitude2 * PI() / 180
SET #Long2Radians = #Longitude2 * PI() / 180
RETURN ACOS(COS(#Lat1Radians) * COS(#Long1Radians) * COS(#Lat2Radians) * COS(#Long2Radians) + COS(#Lat1Radians) * SIN(#Long1Radians) * COS(#Lat2Radians) * SIN(#Long2Radians) + SIN(#Lat1Radians) * SIN(#Lat2Radians)) * #EarthRadiusInMiles
END