SQL Report Builder: Use aggregate function on ReportItem - sql-server

I've entered the following expression for a given cell, which is essentially a dollar value divided by a quantity to get a cents per gallon value, labeled as Textbox41:
=ReportItems!Total_Gross_Profit2.Value / ReportItems!Gallon_Qty3.Value
What I was trying to do is use this expression for an AVG aggregation in another cell =avg(ReportItems!Textbox41.Value), but I'm getting an error:
The Value expression for the textrun
'Textbox79.Paragraphs[0].TextRuns[0]' uses an aggregate function on a
report item. Aggregate functions can be used only on report items
contained in page headers and footers.
Is there some limitation that does not allow aggregations on ReportItems? I've also tried the following, which also did not work:
=AVG(ReportItems!Total_Gross_Profit2.Value / ReportItems!Gallon_Qty3.Value)
Where am I going wrong here?

Regarding your question:
Is there some limitation that does not allow aggregations on ReportItems?
You have your answer in the error message you provided.
As for the resolution, it's hard to give precise guidance with the information you provided, but in general, start thinking in terms of dataset fields instead of report objects. If you're operating from inside a matrix or table, and if the values for 'Total_Gross_Profit' and 'Gallon_Qty_3' look something analogous to this:
= ReportItems!ProfitsFromX.Value + ReportItems!ProfitsFromY.Value
= ReportItems!GallonQtyA.Value + ReportItems!GallonQtyB.Value
Point to the fields directly instead:
= Fields!ProfitsFromX.Value + Fields!ProfitsFromY.Value
= Fields!GallonQtyA.Value + Fields!GallonQtyB.Value
That way, when it comes to aggregation, it's more clear what to do:
= avg(
(Fields!ProfitsFromX.Value + Fields!ProfitsFromY.Value)
/ (Fields!GallonQtyA.Value + Fields!GallonQtyB.Value)
)
And if you find that cumbersome, you can create calculated fields on the dataset object, and reference those instead where appropriate.

Related

How to make dynamic references to tables in Anylogic?

I`ve modeled six machines. Each of them has a different profile of electricity load. The load profile is provided in a table in AnyLogic. Every machine has an own table storing these values. I iterate trough the values to implement the same in TableFunctions. Now I face the following challenge: How can I make a dynamic reference to the relevant table. I would like to pick a specific table in dependence of a machine indice. How can I define a variable that dynamically refers to the relevant table object?
Thank you for your help!
not sure it is really necessary in your case but here goes:
You can store a reference to a database table to a variable of the following type:
com.mysema.query.sql.RelationalPathBase
When selecting values of double (int, String, etc.) type in a particular column, you may get the column by index calling variable.getColumns().get(index). Then you need to cast it to the corresponding type like below:
List<Double> resultRows = selectFrom(variable).where(
( (com.mysema.query.types.path.NumberPath<Double>) variable.getColumns().get(1) ).eq(2.0))
.list(( (com.mysema.query.types.path.NumberPath<Double>) variable.getColumns().get(1) ));
Are you always going to have a finite number of machines and how is your load profile represented? If you have a finite number of machines, and the load profile is a set of individual values - or indeed as long as you can hold those values in a single field per element - then you can create a single table, e.g. machine_load_profile, where the first column is load_profile_element and holds element IDs and further columns are named machine_0, machine_1, machine_2 etc., holding the values for each load profile element. You can then get the load profile elements for a single machine like this:
List<Double> dblReturnLPEs = main.selectValues(
"SELECT machine_" + oMachine.getIndex()
+ " FROM machine_load_profile"
+ " ORDER BY load_profile_element;"
);
and either iterate that list or convert them into an array:
dblLPEValues = dblReturnLPEs.stream().mapToDouble(Double::doubleValue).toArray();
and iterate that.
Of course you could also use the opposite orientation for your columns and rows as well, using WHERE, I simply had a handy example oriented in this manner.

SSRS The textrun uses a First aggregate in an outer aggregate (Different datasets)

Ok, I'm working on a multi-data report that merges data from many servers.
dataset1 = One of six datasets with the data I need.
ds_BusinessDays = A calendar table dataset with Specific dates and numbers that change every day/week/month.
I'm trying to use a SWITCH where MonthName(Date) from dataset1 = MonthName(Date2) from ds_BusinessDays. Then Sum the total count.
I have successfully used similar cross dataset calculations like
SUM(SWITCH when Data = "Product" then 1) / SUM(businessdaysinmonth, "ds_BusinessDays")
This was to get the Average. works like a charm.
=SUM(
SWITCH(Fields!Requested_Month.Value = MonthName(Month(First(Fields!PreviousBusinessDate.Value, "ds_BusinessDays")))
,1)
)
All Fields in ds_BusinessDays dataset are 1 entry results. Example, "PreviousBusinessDay" = "6/21/2019". So I want my code to do something like this.
When MonthName(Date) form dataset1 = MonthName(PreviousBusinessDate) from ds_BusinessDays then 1. Sum all of that up to get my a total for that month.
The problem is that FIRST and SUM are the only fields available to me when using fields from another dataset. They can't be used in an Aggregate within an Aggregate.
Is there a substitute that I can use for First in First(Fields!PreviousBusinessDate.Value, "ds_BusinessDays")?
Why are you using a SWITCH when you only have a single conditional? I think an IIF would be much easier to read. Also, if ds_BusinessDays.PreviousBusinessDate is a single entry, why do you even need FIRST? There should only be one result. If you're trying to do what I think you're trying to do, this expression should do it.
= SUM(IIF(Fields!Requested_Month.Value = MonthName(Month(Fields!PreviousBusinessDate.Value, "ds_BusinessDays")), 1, 0))
To add additional detail, a SWITCH is best used for more than 2 conditional statements. If you're only trying to compare two fields, you can just use a simple IIF. An example of when SWITCH is necessary:
=SUM(SWITCH(Fields!Date.Value = Fields!Today.Value, 1,
Fields!Date.Value = Fields!Yesterday.Value, 2,
Fields!Date.Value = Fields!Tomorrow.Value, 3,
true, 0))
This expression would check Date against three different fields and return a different count for each, ending with an always true condition that catches everything else. Your expression doesn't need a SWITCH.

Using expressions for a value in Paramaters

I have a report that returns various products depending on which product group you select. Most of these products all have similar product codes that allow me to use the LIKE operator to get the required results. However, for one particular product group, I have the following problem:
VSAMPLES
VSAMPLES2016
VSAMPLES2016DD
VSAMPLESADD
VSAMPLESET
VSAMPLESLARGE
VSAMPLESLARGEADD
VSAMPLESNEW
I only need the top two products to be listed. But using 'VSAMPLES% as a parameter value will return all of these products.
Can i write an expression for the parameter value that will use 'VSAMPLES% and 'VSAMPLES2016% to only return these two products?
EDIT
The query is:
SELECT STRC_CODE, STRC_DESC FROM DeFactoUser.F_ST_Products
WHERE STRC_CODE LIKE #ProductCode
I am using LIKE so I don't have to specify dozens of products for each group.
For one Parameter value I am using 'PA.A% This works perfectly because every product starting with PA.A is needed. In the case of VSAMPLES this isn't the case.
Parameter Values are as follows:
So, can I not add a value to the Aspire tab that will return only those two products?
OK, What i was asking might not have been possible. i fixed the issue by altering my query.
SELECT STRC_CODE, STRC_STATUS, STRC_DESC FROM DeFactoUser.F_ST_Products
WHERE STRC_CODE LIKE #ProductCode AND STRC_CODE NOT IN ('VSAMPLES2016DD',
'VSAMPLESADD', 'VSAMPLESET', 'VSAMPLESLARGE', 'VSAMPLESLARGEADD',
'VSAMPLESNEW')
This results in only the two products I needed being returned when i use VSAMPLES% as a value.
Much simpler then I thought.
Thanks for the input into the question I asked.

Salesforce - SOQL Use mod() or similar math functions in SELECT?

I'm trying to query all Opportunities that have a Price that's not a whole number (no decimals) or if its price is not multiple of 10.
Im trying to find prices like: U$S 34,801.23 - U$S 56,103.69 - U$S 50,000.12 etc
But not : U$S 49,500.00 - U$S 19,110.00 etc
There are a lot of opportunities in the database, and i can go through them by code but wanted to know if any of you can think of a way to achieve at leaast a part of this by query.
SOQL won't let you do any calculations. Check docs here and here:
You must supply a native value—other field names or calculations are
not permitted
Generally speaking it's fieldName = value or datefieldname > YESTERDAY (few special literals for date handling).
Easiest would be to create a formula field in the record (think about them like calculated columns in views in normal databases) with your logic. It could be of text type, call it "weird price" ;) Here's the complete formula functions reference - you have MOD(), IF(condition, true, false) etc goodies.
The only caveat is that you can't GROUP BY formula (there also tricks to bypass that ;))
So yeah - if it's one time thing with poor reusability - filter with code. If you can accept the low cost (formulas don't use storage but you might need them for other purposes) - create a field.

MDX query is very slow and returns memory exception in SSRS

I'm trying to get a detailed list of all records where my total amount is more than 100k from the following Multidimensional Expressions (MDX) query:
with member [measures].[total] as
[Measures].[m1] + [Measures].[m2] + [Measures].[m3]
select non empty
[measures].[total] on columns,
non empty filter ([dim1].[h1].allmembers
* [dim1].[h2].allmembers
* [Loss Date].[Date].[Year].allmembers
* [Dim1].[h3].allmembers
, [measures].[total]>100000 and [Measures].[Open File Count]>0) on rows
from [Monthly Summary]
where ([1 Date - Month End].[Month End Date].[Month].&[20120331])
Although I get fast results from creating a stored procedure and the final result is less than 1000 rows, my MDX query runs for ever in SSMS and in SSRS returns a memory exception. Any idea on how to optimize or enhance it?
You could use Having instead of Filter, since it is applied after the Non Empty and you may get better performance (see this excellent blog post by Chris Webb). This would be the new version of the query:
with member [measures].[total] as
[Measures].[m1] + [Measures].[m2] + [Measures].[m3]
select non empty
[measures].[total] on columns,
non empty
[dim1].[h1].allmembers
* [dim1].[h2].allmembers
* [Loss Date].[Date].[Year].allmembers
* [Dim1].[h3].allmembers
having [measures].[total]>100000 and [Measures].[Open File Count]>0 on rows
from [Monthly Summary]
where ([1 Date - Month End].[Month End Date].[Month].&[20120331])
I would recommend a couple of changes.
First, do you really want the All member of each of your dimensions to be returned in the query? They will be included if they meet the condition in the filter. Also, I have found changing a where clause to a subselect to perform better in some cases. You need to test to see if it changes performance. Next, you can reduce the number of members that you're filtering by using a NonEmpty function first, by putting it inside the Filter function. Also, in some cases, using a polymorphic operator (*) performs worse than using a CrossJoin function or creating a tuple set of your members. The NON EMPTY on columns is unnecessary when you have only one item on the axis. I've combined all of these suggestions below:
with member [measures].[total] as
[Measures].[m1] + [Measures].[m2] + [Measures].[m3]
select
[measures].[total] on columns,
filter (
nonempty(
([dim1].[h1].[h1].members,
[dim1].[h2].[h2].members,
[Loss Date].[Date].[Year].members,
[Dim1].[h3].[h3].members)
, [measures].[m1]),
, [measures].[total]>100000 and [Measures].[Open File Count]>0) on rows
from
(select [1 Date - Month End].[Month End Date].[Month].&[20120331] on columns
from [Monthly Summary])
See this for a bit of explanation on the NON EMPTY versus NonEmpty: http://blogs.msdn.com/b/karang/archive/2011/11/16/mdx-nonempty-v-s-nonempty.aspx. In some cases putting a NonEmpty function inside a Filter function can produce a performance hit, sometimes not - you need to test.
The problem might be in a dimension or cube design (storage engine problem) and not in the query (formula engine problem). You can diagnose using the techniques here: http://www.microsoft.com/en-us/download/details.aspx?id=661. The whitepaper was written for SSAS 2005, but still applies to later versions of SSAS.
To reduce memory, order your dimensions.
Instead of:
[dim1].[h1].allmembers
* [dim1].[h2].allmembers
* [Loss Date].[Date].[Year].allmembers
* [Dim1].[h3].allmembers
Use
[dim1].[h1].allmembers
* [dim1].[h2].allmembers
* [Dim1].[h3].allmembers
* [Loss Date].[Date].[Year].allmembers
Under the covers, SSAS will inner join the dim1 members and outer join the Loss Date members.

Resources