SSRS Division issue in column grouping - sql

Problem: Having trouble getting an accurate division on a "sub-matrix" when using drill down, works on totals but not detail level.
Report:
Visual Studio Design of the report:
Now the current SSRS expression I'm using in the "% Of total" section is:
=Code.SafeDivide(Fields!Orders.Value , Sum(Fields!Orders.Value))
and the embedded code was a recommendation from this post:
Public Function SafeDivide(ByVal Numerator As Decimal, ByVal Denominator As Decimal) As Decimal
If Denominator = 0 Then
Return 0
End If
Return (Numerator / Denominator)
End Function
Data results looks like:
Now if you look at the first picture and calculate the divison of the highlighted values, i would expect the outcome to be 72% not 6%.
Any ideas? Maybe i've tried a few things but seem like im chasing my tail, would of though this would be simply straight forward.

It looks like you need to pass in a sum rather than a single order amount, and then tell your existing sum function the overall group to sum e.g. I think your expression should probably be something like this:
=Code.SafeDivide(Sum(Fields!Orders.Value), Sum(Fields!Orders.Value, 'Overall Group Name'))

Related

SUMIF Conditional based sum

I'll explain whats going on with the left table first:
Qty1 Normal Calculates a sum from another column, Qt2 Normal calculates a product.
The table to the right is supposed to calculate based on an entry in column B, the result in both columns M and N (even when negative).
So basically, no matter where on Column B there will be an entry for "EUR" its suppose to sum Qty1 Normal and Qty2 Normal
I've been spending the last 2.5 hours trying to figure out, trying SUMPRODUCT, IF(SUM( and many other arguments I could try coming up and googling.
The function looks as such:
=SUMIF(B:B,"EUR",(M:M:N:N))
the result should be (826000) and unfortunately I couldn't figure out what is wrong with the function I wrote.
If there is a solution within VBA that will be great, however I believe we can solve this within the simple function regions.
Thank you!!

Qlik View: Get Values WHERE (value2 = max)

i have a relativly simple problem:
i have a Dataset that consists of an id(not for entry but for specific object), an age of the object and a power value.
So what i get is a lot of entries where there is a power at a specific age for a specific object.
I want to create a diagram that shows the average of all power values at the highest age over all objects(ids).
In SQl this basically would look something like SELECT power WHERE max(age).
Can anybody suggest a smart way how to this in a smart way in qlik view?
I already tried using the sum() function with total and aggr it over all ids but i keep getting weird results.
I tried using set analysis with aggr ({} power, id) but it doesnt work.
Edit: I tried
aggr(if (age= max(age), power), id)
but as soon as i select an id with more than one entry (different ages) there is no data displayed. Same when i remove the aggr function.
And:
Avg({$<age = max(age)>}Power)
Displays nothing at all (it also displays an error)
Also tried:
Sum({$ <age= {$(=max(age))} > } power )
Still nothing.
Thanks
Julian
Solved it with firstordervalue:
avg(aggr(firstsortedvalue (power, -age), id))
Yes Set Analysis should work.
Something like:
Avg({$<age = max(age)>}Power)
Alternatively, you can use a conditional sum as well:
if (age = max(age), avg(Power))
Aggr is used to run a statistic over a list of records with a 'group by' condition as in SQL

SQL Server Report Builder SUM IF

I have a table which display various data and what I want is it to calculate a percentage in which the total has increased by, so for example:
Total is £1000
TotalAfterMarkup is £1500
=SUM(Fields!Total.Value -
Fields!TotalAfterMarkup.Value) /
(Fields!TotalAfterMarkup.Value)
the above code calculates the Percentage to -50% which is incorrect but ill be able to work that out. What i want is to now put this statement into an SUM IF statement. currently i get the #Error if the TotalAfterMarkup < 1 so i need something like
IF TotalAfterMarkup.Value >0 THEN
=SUM(Fields!Total.Value -
Fields!TotalAfterMarkup.Value) /
(Fields!TotalAfterMarkup.Value)
ELSE 0.00%
is this possible, thanks for any help guys
Unfortunately I don't have enough rep to comment, otherwise I wouldn't post this as an answer. Really, I need a little more information. Are you doing this as an expression within the report builder or as part of your dataset?
If its part of your dataset then I suggest using a case statement.
case
when TotalAfterMarkup.Value >0
then SUM(Fields!Total.Value -
Fields!TotalAfterMarkup.Value) /
(Fields!TotalAfterMarkup.Value)
else '0.00%'
end [MyFieldName]
Using an IIF Statement: ("Dataset = Your Dataset Name")
=IIF(Fields!TotalAfterMarkup.Value, "CostTable") >0, SUM(Fields!TotalCost.Value, "CostTable") - (Fields!TotalAfterMarkup.Value, "CostTable") / (Fields!TotalAfterMarkup.Value, "CostTable"), "0.00%")
I think this should work:
=IIF(TotalAfterMarkup.Value > 0,(SUM(Fields!Total.Value -
Fields!TotalAfterMarkup.Value)/(Fields!TotalAfterMarkup.Value)),0)
The IIF function is the one you use for evaluating conditions in SSRS:
Expression Examples (Report Builder and SSRS) - See decision function section

SQL Report Builder: get value from group within tablix

Please forgive the vague title of this question. Perhaps the below will ask my question better.
Consider the below aggregated table:
Fruit Units FruitSales%
----- ----- -----------
Apples 10 ?
Oranges 20 ?
Bananas 10 ?
NonFruit 10 ?
TOTAL 50 ?
I need the FruitSales% column to be: Fruit / (Total - NonFruit)
If NonFruit is a product name of its own, how do I get its value for use in other calculations in the tablix?
I imagine my formula for the FruitSales% is something like:
Sum(Fields!Units.Value) / (ReportItems!txtTotalUnits.Value - SumIf(Fields!Fruit = "NonFruit", Fields!Units.Value)
However, SumIf does not exist and even if it did, it would be specific to the current row.
And while I'm here, ReportItems!txtTotalUnits.Value, I have obviously named that text box, but is there a cleaner way to reference it?
Say the underlying DataSet (which I've called FruitDataSet) looks like this:
I've created a simple report based on this data:
The Fruit Sales % expression is:
=Sum(IIf(Fields!fruit.Value <> "NonFruit", Fields!units.Value, 0))
/ Sum(IIf(Fields!fruit.Value <> "NonFruit", Fields!units.Value, 0), "FruitDataSet")
This gives what I think is the correct results:
There are two things to note about the expression:
By running the Sum against an IIf expression, you can control what gets included in the totals - here I'm setting NonFruit explicitly to 0.
By setting the Scope of the aggregate expression, you can get overall totals to use to work out total percentages - in the report I'm getting a total using FruitDataSet and comparing this to the group-level total to get a % value.
The way you're referencing the textbox total is fine; the only other option would be to use an expression each time you want the total - if this is outside a Tablix you would need to explicitly set the Scope, e.g. the DataSet.

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;