BASIC Questions: Using ROUND for calculations - sql

I am in Google's Data Analytics course and every now and then I get to a spot where I could just press on, but I want to know the answer anyway.
We are learning embedded calculations and a very simply equation was given:
`
SELECT
Date,
Region,
Total_Bags,
Small_Bags,
(Small_Bags / Total_Bags) * 100 AS Small_Bags_Percent
FROM `shaped-fx-370703.avocado_data.avocado_prices`
WHERE
Total_Bags <> 0
`
Resulting column from calculation
I would like to know how to use ROUND so that the result in Small_Bags_Percent only go out to 1 decimel
I understand the syntax of round is ROUND(integer,decimel places) but I don't know how to point the "integer" to the results in Small_Bags_Percent. I've tried THEN and even
ROUND(((Small_Bags / Total_Bags) * 100 AS Small_Bags_Percent),2)
``` (hey, I'm just seeing what sticks lol)

The ROUND function goes round the calculation but not the alias for the calculation e.g.
ROUND((Small_Bags / Total_Bags) * 100,2) AS Small_Bags_Percent

Related

How to limit the character amount you are selecting from

I'm trying to average a field and it's very simple to do but there are some problems with some values. There are values I know are way too big and I was hoping to exclude them by the number of characters (I would probably put 4 characters max).
I'm unfamiliar with a sql clause that could execute this. If there is one that would be great.
select avg(convert(float,duration)) as averageduration
from AsteriskCalls where ISNUMERIC(duration) = 1
I expect the output to be around 500-1000 but it comes up as an 8 digit number.
That is easy enough:
select avg(convert(float,duration)) as averageduration
from AsteriskCalls
where ISNUMERIC(duration) = 1 and length(duration) <= 4;
This will not necessarily work, of course, because you could have '1E30', which would be a pretty big number. And it would miss '0.001', which is a pretty small number.
The more accurate method uses try_convert():
select avg(try_convert(float, duration)) as averageduration
from AsteriskCalls
where try_convert(float, duration) <= 1000.0
And that should probably really be:
where abs(try_convert(float, duration)) <= 1000.0

Code Not calculating correctly Cast /NullIF

I’m trying to calculate CNC machine efficiency. My code doesn’t calculate correctly. I’m not sure why. For instance, The Completed value is 2. The PPHOURGOAL is 1. The 8 is for an 8-hour shift.
cast(((Completed / 8) /NULLIF(Completed,0) / (PPHOURGOAL * 8) )* 100 as dec(5,4)) as EightHourShiftEfficiency, ---Divide the previously calculated production rate by the maximum rate and multiply by 100 to calculate the efficiency rate.
Calculation should be as ((2/8)/(1*8))*100 = 2. Which should translate to ((.25)/(8))*100=2
But the system is returning 1.5625 instead.
I am guessing that integer division is the culprit. Does this do what you want?
cast(((Completed / 8.0) /NULLIF(Completed, 0.0) / (PPHOURGOAL * 8.0) ) * 100.0 as dec(5, 4)) as E
Found the error of my ways. My select statement was doubling rows that caused my calculations to be off.

Rails Decimal Calculations with funky output

I'm trying a few decimal calculations, in a Rails app, but am getting some weird results.
#pprice = item.price - (( item.price / 100 ) * promo.discount)
#pprice = item.price - promo.discount
Each value (item.price, promo.discount etc) is a decimal. However, when trying to calculate I get mixed results, none of them being the correct total. The results range from nil, 0.0 and -2.0 depending on whether I have .to_f included.
The first calculation is based on a percentage discount and the second on a straight money reduction.
I have performed the calculations in the view (to test) and they display correctly, but when they are moved over to the controller, I get the errors.
Any help is much appreciated.
since u r converting the values to float, ur calculation results arent precise.
see String, decimal, or float datatype for price field?

SQL math syntax difficulty with division

Can't understand why I can't get the correct answer. I'm trying to calculate a net margin percentage but the divide portion is being ignored. Hopefully really simple one?
SUM(
(dbo.K3_TradeTeam_Sales2.TotalSales - dbo.K3_TradeTeam_SalesReturn3.TotalCredits)
ISNULL(dbo.K3_TradeTeam_Purch1.TotalPurchases, 0) /
dbo.K3_TradeTeam_Sales2.TotalSales
) AS NetMargin
To get a net margin you probably want an expression like this,
(
SUM(
dbo.K3_TradeTeam_Sales2.TotalSales
-
COALESCE(dbo.K3_TradeTeam_SalesReturn3.TotalCredits, 0.0)
-
COALESCE(dbo.K3_TradeTeam_Purch1.TotalPurchases, 0.0)
)
/
SUM(
dbo.K3_TradeTeam_Sales2.TotalSales
)
) AS NetMargin
However, without knowing your schema I couldn't say for sure. This would also fail miserable when you have 0.0 total sales.
I'm assuming that your want the sum of net profits for each realtion divided by the sum of the total revenue for each relation. This would give you the cumulative profit margin for all relationships.
The sql logic should work.
Are you sure that TotalPurchases is not null? Because this makes it look like the devide is ignored, but the devide just returns 0. So I'm doing minus zero!
examples:
select SUM((200 - 100) - ISNULL(100, 0) / 10) AS NetMargin --returns 90
select SUM((200 - 100) - ISNULL(null, 0) / 10) AS NetMargin --return 100
When I am having trouble getting a math formula to work, I change the select temporarily to simply see the values of each of the fields as well as the calculation. Then I can do the calualtion manually to see how I am getting the results I am getting which alwmost always points me to the problem.
select
dbo.K3_TradeTeam_Sales2.TotalSales,
dbo.K3_TradeTeam_SalesReturn3.TotalCredits,
ISNULL(dbo.K3_TradeTeam_Purch1.TotalPurchases, 0),
dbo.K3_TradeTeam_Sales2.TotalSales
From...
I also never do a division without a case statement to handle the divisor being 0 problem. Even if I think it can never happen, I have seen it burn people too often not to consider that something (including bad data entry) might make it happen in the future.

MDX geographic distance calculation

I'm using SQL Server 2005 Analysis Services and I'm trying to calculate distance inside of an MDX query - so that I can get counts of the items that are near my current location. I've created a dimension with Latitude & Longitude, and have also created a .NET assembly to do the math - but am having a hard time getting it all to work out in the query.
My query to find items in a 100 mile radius looks something like this:
select FILTER([DimProducts].[Product].[Product],
ZipCalculatorLib.GetDistance(43.474208, [Zip].[Latitude], 96.687689, [Zip].[Longitude]) < 100) on rows,
[Measures].[RowCount] on columns
from MyCube;
And my distance code in .NET looks like this:
public static double GetDistance(double startLat, double endLat,
double startLong, double endLong)
{
return Math.Sqrt(Math.Pow(69.1 * (startLat - endLat), 2) + Math.Pow(Math.Cos(endLat / 57.3) * 69.1 * (startLong - endLong), 2));
}
However, when I run that query, I come up with zero records. If I change the distance from 100 to 10000 - I get counts similar to what should be in the 100 mile radius. It looks like the .NET class isn't doing the square root - but I've tested that code many times over, and it looks right.
Does anyone have any suggestions as to where I should look to fix my problem?
EDIT:
I started to wonder if maybe the latitude and longitude weren't being passed into my GetDistance function correctly - so I added a line of code there to throw an exception to show me what they were. I added the following:
throw new ArgumentException("endLat", string.Format("endLat: {0}, endLong: {1}", endLat, endLong));
And now when I run my query, I get the following error:
Execution of the managed stored
procedure GetDistance failed with the
following error: Exception has been
thrown by the target of an
invocation.endLat Parameter name:
endLat: 1033, endLong: 1033.
So now the question becomes: how do I get my actual latitudes values to pass through that function in the filter? It looks like just a language code is being passed in now.
[Zip].[Latitude] is a member expression. In order to pass this to a function as a numeric value SSAS will return the equivalent of ([Zip].[Latitude], Measures.CurrentMember). And you can't directly filter one dimension based on another in MDX. By definition, different dimensions are completely independent and in OLAP terms every product could potentially exist at every Zip location.
What I suspect that the logic would have to look like is the following:
select
NONEMPTY([DimProducts].[Product].[Product] *
FILTER([Zip].[Zip].[Zip] , ZipCalculatorLib.GetDistance(43.474208, [Zip].[Latitude].CurrentMember.MemberValue, 96.687689, [Zip].[Longitude].CurrentMember.MemberValue) < 100),[Measures].[RowCount]) on rows, [Measures].[RowCount] on columns
from MyCube;
This gets all of the Zip members that have a latitude/longitude within 100 miles, cross joins that with products and then returns those that have a nonempty RowCount.
How are you sure that you are calculating this in miles?
I'm not sure if SQL Server 2008 is availuable, if it is, you should use its geography datatype to calculate distances.
If not, check libraries like SharpMap and Proj.Net - They will let you build a true geographic point and calculate accurate distances between those objects.
I ended up solving my problem using a subcube. by creating the subcube, I was able to filter for the distance - and then after that just did a select for the dimension that I was looking for. Here's what I ended up with...
create subcube MyCube as
select Filter
(
(
[DimLocation].[Latitude].[Latitude],
[DimLocation].[Longitude].[Longitude]
),
(
ZipCalculatorLib.GetDistance(
43.474208,
[DimLocation].[Latitude].CurrentMember.MemberValue,
96.687689,
DimLocation.Longitude.CurrentMember.MemberValue) < 100
)
) on 0 from MyCube;
select DimProducts.Product.Product on rows,
Measures.RowCount on columns
from MyCube;