Getting Scope error on SUM(IIF()) of rows from other table - reporting-services

Currently getting a scope error using the code below, what we're trying to do is count the number of rows that match the conditions we have:
=
SUM(
IIF(
Fields!Defect_Category.Value = "Packaging"
& Fields!Defect_Category.Value = "Major"
& Fields!WorkOrderDisplayID.Value = Fields!Work_Order_Id.Value,
1, 0),
"dsDefects"
)
Work_Order_Id is the "key" of the dsGeneral dataset which is the current scope/dataset of the tablix where we're trying to implement this. Any way we can fix this?
My understanding is that the Scope parameter of SUM is referring to the dataset we're trying to get the sum of (or count of, in this case). When I specify "dsDefects" as the scope of SUM, I get the following error:
The Value expression for the text box 'Textbox101' refers to the field
'Work_Order_Id'. Report item expressions can only refer to fields
within the current dataset scope or, if inside an aggregate, the
specified dataset scope. Letters in the names of fields must use the
correct case.
However, if I remove the scope parameter value, I'm getting the following error:
The Value expression for the text box 'Textbox101' refers to the field
'Defect_Category'. Report item expressions can only refer to fields
within the current dataset scope or, if inside an aggregate, the
specified dataset scope. Letters in the names of fields must use the
correct case.

I think you will need something like this...
=
IIF(
Fields!Defect_Category.Value = "Packaging"
& Fields!Defect_Category.Value = "Major",
LOOKUPSET(Fields!WorkOrderDisplayID.Value, Fields!WorkOrderDisplayID.Value, Fields!WorkOrderDisplayID.Value, "dsDefects").Length,
0)
I'll give a simple example of counting matches from another dataset and that might help you put the two together to get an solution.
If I create two datasets with the following queries, called dsEmp and dsDev respectively
dsEmp
DECLARE #e table (empid int, empname varchar(10))
insert into #e values
(1, 'Bob'), (2, 'Dave')
SELECT * FROM #e
dsDev
declare #d table(empid int, device varchar(10))
insert into #d VALUES
(1, 'Phone'),
(1, 'Laptop'),
(1, 'Desktop'),
(2, 'Phone'),
(3, 'Tablet')
SELECT * FROM #d
Then in my report I add a table bound to dsEmp showing the empID and empName and then in the final column I use the following expression
=LookupSet(
Fields!empid.Value,
Fields!empid.Value,
Fields!empid.Value, "dsDev"
).Length
I get this final output
As lookupset returns a collection, the collection's length is, in fact, the number of items contained in the collection.

Related

How to SUM the values from group in SSRS which are distinct

I have a report where I want to calculate the Grand total but ignore the values of a group which have same value. Below are my tables and the data. The Package No column is grouped and will be unique always, but every unique Package may or may not have same dimensions. I want to SUM the dimension (Length, Width and Height) and it Package No has multiple items in it then have to consider only the first row for summing up the values as the dimensions will remain the same for all the items within the same Package. Can anyone please help me to achieve this result?
Assuming the data that gets returned from your dataset query looks like the sample you show in the image then you should be able to do something like...
=SUM(IIF(Fields!RowNum.Value = 1, Fields!Length.Value, 0))
EDIT after OP update
If the RowNum column is not in your dataset then you will need to add it.
If you dataset query is just a script then it should be as easy as something like this...
SELECT *
, RownN = ROW_NUMBER() OVER(PARTITION BY PackageNo ORDER BY Item)
FROM myTable
If the dataset is the result of a stored proc then you might have to change the dataset query to something like
CREATE TABLE #t (PackageNo varchar(50), Length int, Width int, Height int, Item varchar(50))
INSERT INTO #t
EXEC myStoredProc
SELECT *
, RownN = ROW_NUMBER() OVER(PARTITION BY PackageNo ORDER BY Item)
FROM #t
Once one of the above options are been taken then you should be able to simply apply the =SUM(IIF(Fields!RowN.Value = 1, Fields!Length.Value, 0))
expression in your report totals.

change colour of highest total column value in rdl report

In rdl report i am showing total column as sum aggregation, i want to highlighte highest of that total.
This is a generic answer that makes lots of assumptions. As you question does not contain enough info for a definitive answer but hopefully this will give you enough that you resolve your problem.
To recreate this do the following (and then adapt to suit your specific situation)
Create a new report.
Add a datset and use the following query as the dataset query
-- create some sample data
DECLARE #t TABLE(Customer varchar(10), Product varchar(10), Quantity int)
INSERT INTO #t VALUES
('Dave', 'Hammer', 6), ('Dave', 'Saw', 6),('Dave', 'Hammer', 1),
('George', 'Drill', 3),('George', 'Hammer', 6),('George', 'Saw', 6),('George', 'Hammer', 1),
('Mary', 'Drill', 3),('Mary', 'Hammer', 6),
('Jane', 'Saw', 6),('Jane', 'Hammer', 1),('Jane', 'Drill', 3)
-- return the sample data plus a total per customer
SELECT *
, CustomerTotal = SUM(Quantity) OVER(PARTITION BY Customer)
FROM #t
This give use the following results
Next add a Matrix control to the report.
Drag the fields to the matrix as shown here
Customer to "Rows"; Product to "Columns"; Quantity to "Data"
You should now have a matrix with some row and column groups shown underneath.
next we need to add a total column so right-click the "Product" column group select "Add Total => After"
Finally, we need to test if the value in the total column matches the largest CustomerTotal in our dataset. If it does match then change the textbox color property to "Red".
We can use this expression in the textbox color to do this..
=IIF(
Sum(Fields!Quantity.Value) = MAX(Fields!CustomerTotal.Value, "DataSet1"),
"Red",
"Black")
What this does is take the total quantity in the current scope (the entire row) and compare it to the highest CustomerTotal with the scope "Dataset1" which is the entire dataset. If the two match, set the vlue to "Red", else set it to "Black"
With a bit of a tidy-up the final output looks like this.

SQL SUM function for a column with integer name

I'm trying to return the sum of a column with an integer name (for example, a column named 251)
CREATE FUNCTION myfun(cid varchar(255))
RETURNS float
BEGIN
RETURN (SELECT SUM(`cid`) FROM percentages);
END
I want it to return the sum of all the rows of the cid column of my percentages table, but it's instead returning the sum of the cids.
For example: if i call myfun(251)
if the values in the columns 251 are 1, 2, 3, and 4, I would expect an output of 1+2+3+4=10
But it is returning 251+251+251+251=1004 instead
You cannot do what you want with standard SQL. You simply cannot parameterize a column name, even with backticks, using regular SQL.
I can give you the hint that dynamic SQL (prepare/exec) can do what you want.
More importantly, I want to point out a flaw in your data model. You presumably have many columns with the same information. Instead, this data should be on separate rows. Something like:
id col val
SQL is usually better with more rows rather multiplying columns.
using dynamic sql and putting the column name in brackets, should work:
something like:
declare #sql varchar(255) = 'SELECT SUM([' + #cid + ']) FROM percentages'
exec(#sql)

If one value is returned for a parameter then set as default, if more than one value is returned do not select a default

We have a series of reports which return a set of values for a parameter based on the userID. This works and we're happy with the way it works.
Now we need to implement a default parameter setting. The logic being
If there is only one value in the parameters available dataset, then set that as the default.
If there is more than one value in the parameters available dataset, then leave the parameter blank.
This is what I have so far - I know I have the following issues:
-Parameters cannot read fields, therefore I need the expression to look at the dataset as a whole.
-I'm unsure what my then statement should be to allow the user to review all available values without them being selected.
=IIf(CountDistinct(Fields!storekey.Value, "UserStoreVerification")) = 1, First(Fields!storekey.Value, "UserStoreVerification")," ")
You can create a separate dataset to populate the "default values" for the parameter. In this dataset you can add logic to count the number of rows that would be returned by the other dataset that provides the parameter values. If there are greater than 1 values returned by the first query then the second dataset just returns NULL (i.e. no default values are selected).
Example
If your original dataset for parameter values (e.g. "dsParamProduct") used a query like this:
SELECT ProductNumber
FROM dbo.Product
WHERE Available = 'Yes'
Then the dataset query for the default values (e.g. "dsParamProductDefault") could be something like this:
DECLARE #ValueCount INT
SELECT #ValueCount = COUNT(*)
FROM
(
SELECT ProductNumber
FROM dbo.Product
WHERE Available = 'Yes'
) vals
IF #ValueCount = 1
SELECT ProductNumber
FROM dbo.Product
WHERE Available = 'Yes'
ELSE
SELECT NULL
Supplying "NULL" as the default value when there is more than one value will mean none of the available values are selected and therefore the user will have to manually select them (assuming that NULL isn't a valid value for your parameter - if it is then make sure the default query will return something else that is definitely not valid). If there is only one possible value then the default value query just returns the same result as the parameter values dataset, which means that the parameter value will be selected.
Set up another parameter that is dependent on the first, same type but slightly different name, and do your code at bottom with one suggested change:. Change " " at the end before the parenthese end to be 'NOTHING' instead. I believe this is interpreted by SQL as NULL which is what you want.
Now you should be getting population of the parameter so I would debug and check it by just dragging and dropping it to the design surface and it should be black if you have more than one default value. You can optionally make this parameter 'hidden' once you can confirm it works.
Now you trick your main dataset with a nifty predicate (or else use some other logic if it suits you better)
Where value = isnull(#DependentParam, value)
Basically this is stating "if the parameter is not null use it, else equate the clause to be everything as it will assume value = value".

SSAS (MDX) - Filtering Dataset based on another Dataset

I have a mdx report on a cube. As available values for division number report parameter I have an autogenerated dataset (dataset1, with all divisions in company) which query looks like this:
WITH MEMBER [Measures].[ParameterCaption] AS
[Dim Division].[Hierarchy].CURRENTMEMBER.MEMBER_CAPTION
MEMBER [Measures].[ParameterValue] AS
[Dim Division].[Hierarchy].CURRENTMEMBER.UNIQUENAME
MEMBER [Measures].[ParameterLevel] AS
[Dim Division].[Hierarchy].CURRENTMEMBER.LEVEL.ORDINAL
SELECT {[Measures].[ParameterCaption], [Measures].[ParameterValue], [Measures].[ParameterLevel]}
ON COLUMNS ,
[Dim Division].[Hierarchy].ALLMEMBERS
ON ROWS
FROM ( SELECT ( STRTOMEMBER(#FromDimDateHierarchy, CONSTRAINED) : STRTOMEMBER(#ToDimDateHierarchy, CONSTRAINED) )
ON COLUMNS
FROM [ArveCubeBiceps]
)
I have another dataset (dataset2), which consists of only those division numbers, which logged in user is supposed to be able to view (data supplied by a procedure). I need to filter dataset1 available values by the values of dataset2.
-I can't just use the dataset2 as available values for division number, since report query is MDX, and expects tuples, which dataset2 doesn't provide. When I try to concatenate dataset2 values into tuples, I get an error that I can`t use "&" for Object() type.
-When I create a hidden parameter on report, which available and default values are those from dataset2, and then apply a filter expression to dataset1 query, which says "DivisionID in #hidden_parameter" - I get no available values for the Division parameter ( I checked the tables, all data is there )
What do I have to do to get this filter expression working... please help anyone :)
#mmarie
second dataset is created by stored procedure:
USE [Biceps]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ArveDivisionsByUserID]
#ldapuid nvarchar(30)
AS
BEGIN
declare #hier as hierarchyid
declare #managerID as int
select #managerID = em.employeeID from Dim_Employee2 em where em.ldapuid = #ldapuid
select #hier = dv.hier from Dim_Division dv where dv.managerID = #managerID and hier is not null order by hier desc
select divisionID from Dim_Division dv where hier.IsDescendantOf(#hier)=1 order by hier
END
#FrankPI - offtopic
don't know why, but I used ctrl+k for code, but it`s still regular text :(
If you can change the second query, then this could return the list of allowed members as a set definition string instead of a list of members, using e. g. the SetToStr function. This could then be used in the first query as a parameter replacing the text [Dim Division].[Hierarchy].ALLMEMBERS for the rows by StrToSet(#AllowedDivisionSet, CONSTRAINED).
If the result sets are not huge, the easy way is to do this is with a filter on the Dataset and NOT in MDX:
Add a Boolean filter in which the Expression is =True and the Value is something like this:
=iif(instr(join(Parameters!DataSet2Parameter.Value,","),
Fields!ToDimDateHierarchy.Value)=0,True, False)