How use NULL value SSRS parameter to retrieve rows containing NULLS - reporting-services

I've read many posts concerning NULLS and SSRS report parameters, but none of them appear to solve my problem.
I have a user-selectable SSRS report parameter #NoteType which can be 1, 3, 4 or NULL. The database table I'm working with (eventText) has a column NoteValue containing 1 of those 4 values. Unfortunately, I can't alter the table design to substitute an integer for that NULL value.
My report works fine if #NoteType = 1, 3 or 4; but not if #NoteType = NULL. If #NoteType = NULL then, depending on my paramaterized WHERE clause (discussed below) my report has either no rows, or it has all of the rows for which NoteValue = 1, 3 or 4. I can't figure out how to retrieve the rows for which NoteValue = NULL if the user selects #NoteType = NULL.
I've configured the #NoteType parameter to allow NULL values, with Note Value as the parameter's value field and Note Type as the label field. The parameter values are obtained from a UNION query:
SELECT ett.NoteValue AS [Note Value],
ett.NoteDescription AS [Note Type]
FROM eventTextType ett
UNION
SELECT NULL AS [Note Value],
'Blank' AS [Note Type]
ORDER BY [Note Type]
The eventTextType table has only 3 rows in which the NoteValue column value is 1, 3 or 4 respectively. There is no row with NoteValue = NULL in the eventTextType table, but there are many such rows in the eventText table. That's why I'm using a UNION query to include NULL as one of the #NoteType parameter values.
The UNION query's output is:
Note Value Note Type
4 Annuity
1 Balance
NULL Blank
3 Division
I suspect that my problem is in the WHERE clause which uses the #NoteType parameter to retrieve rows for the report. Here's what I have tried:
WHERE et.NoteValue = #NoteType -- works fine for #NoteType = 1, 3 or 4; but no rows are returned if #NoteType = NULL
WHERE et.NoteValue = IIF(#NoteType IS NULL, NULL, #NoteType) -- same result
WHERE et.NoteValue = CASE WHEN #NoteType IS NULL THEN NULL ELSE #NoteType END -- same result (expected, since this is equivalent to the IFF version)
WHERE et.NoteValue = COALESCE(#NoteType, et.NoteValue) -- works fine for #NoteType = 1, 3 or 4; but if #NoteType = NULL returns all rows with NoteValue column value 1, 3 or 4 but no rows with NoteValue column value = NULL
What WHERE clause should I be using?

Assuming that your dataset for your main dataset is a dataset query (not a stored proc) then I would simply add a valid parameter value (I've used 0 in this exmaple) to the parameter list and substitute that in the dataset query.
So, change the dataset query that provide parameter values to
SELECT ett.NoteValue AS [Note Value],
ett.NoteDescription AS [Note Type]
FROM eventTextType ett
UNION
SELECT 0 AS [Note Value],
'Blank' AS [Note Type]
ORDER BY [Note Type]
Now in you main dataset query you can change your where clause to this (which will also handle multi-value parameters if that's required)
WHERE ISNULL(et.NoteValue, 0) IN(#NoteType)
Unless I've missed something obvious, that should be it.

Related

How to not COUNT a value in SSRS matrix when value is NULL

I cannot make the my expression NOT count a NULL value in my SSRS matrix.
In my SSRS matrix, I have 2 columns one for AppraisalCompany and a count under the SubmittedDate column. In my report this what is happening:
Per Derrick's suggestion here is the change I made in the ColumnGroup properties for the SubmittedDate:
Here is my expression change in the ColumnGroup properties:
Unfortunately I got this error:
I'm suspicious of your Dataset, I'm not entirely sure how you're getting a null value to return 1 in the COUNT. I have been unable to reproduce your results.
Dataset Query
SELECT 'Drive In' AS AppraisalCompany, NULL AS SubmittedDate
UNION
SELECT 'Photo App - English', 'Dec-18'
Next I created a Row Group on AppraisalCompany and a Column Group on SubmittedDate.
I filtered the column group to remove the null grouping, using the expression =IsNothing(Fields!SubmittedDate.Value), operator <>, and Value true.
In the textbox in the matrix I used [Count(SubmittedDate)].
OUTUT
Appraisal Company | Dec-18
-------------------------------
Drive In | 0
Photo App - English | 1
By a Decimal (Number) datatype Nothing and 0 are the same. You can test this.
Put a tablix into your report with year from 2017 to 2019. Then put the year in a column of the tablix as a number format, then write the following expression in the detail textbox:
=CDec(IIF(CDec(Fields!Year.Value) = 2017, 0, Nothing))
After executing your report you will notice that every value in the year column is 0.
The same goes for the check. Both of these expressions will always return Yes. I basically check for 0 and the second one for for Nothing:
=IIF(CDec(IIF(CDec(Fields!Jahr.Value) = 2017, 0, Nothing)) = 0, "Yes", "No")
=IIF(CDec(IIF(CDec(Fields!Jahr.Value) = 2017, 0, Nothing)) = Nothing, "Yes", "No")
But remember your textbox/column has the be a number format.
So if you want to return Nothing and you display it in a number format textbox, it will show you a 0.
With this in mind it will make sense that a Count() returns the value 1 for 0 AND Nothing. So basically this will do the trick:
'Cont
=Sum(IIF(Fields!YourValue.Value = Nothing, 0, 1))

SSRS 2012 using switch statement with LookupSet count in group footer

Apologies for the long post.
I have an SSRS 2012 report looking at 2 datasets, Dataset1 and Dataset2.
Dataset2 may return 0, 1 or 2 records, so I'm using LookupSet to do this. From the records returned, I need to display several fields.
The report is grouped by Main_ID. In the footer of Main_ID, I am counting the number of returned records from Dataset2.
=LookupSet(Fields!MainID.Value, Fields!MainID.Value, Fields!Record_Name.Value, "Dataset2").Length
This works fine, I'm getting 0, 1 or 2 as appropriate.
In Dataset2 the field:
HasIP
will be used to determine which record in the array I display (as I need to test a field value in Dataset2).
I'm trying to use a switch statement to use the length of the LookupSet array to return the correct fields.
If there are no records (eg length of array = 0) then return the
number 2
If there is 1 record (eg length of array = 1), then return
Record_Name
If there are 2 records (eg length of array = 2), then
check the field HasIP.
If HasIP = YesYes, then return the Record_Name of that matching entry
If HasIP = YesNo, then return the Record_Name of that matching entry.
If all else fails, return the number 2
This is what I'm up to at the moment.
=Switch(
'if no returns returned, display the numeral 2
LookupSet(Fields!Main_ID.Value, Fields!Main_ID.Value, Fields!Record_Name.Value, "Dataset2").Length=0, 2,
'if one return returned, then display Record Name
LookupSet(Fields!Main_ID.Value, Fields!Main_ID.Value, Fields!Record_Name.Value, "Dataset2").Length=1,
LookUp(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Record_Name.Value,"Dataset2"),
'if two records returned, check the HasIP field. If HasIP = YesYes, then use this combination first.
LookupSet(Fields!Main_ID.Value, Fields!Main_ID.Value, Fields!Record_Name.Value, "Dataset2").Length=2 AND
LookUpSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!HasIP.Value,"Dataset2")(0)="YesYes",
LookUpSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Record_Name.Value,"Dataset2")(0),
LookupSet(Fields!Main_ID.Value, Fields!Main_ID.Value, Fields!Record_Name.Value, "Dataset2").Length=2 AND
LookUpSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!HasIP.Value,"Dataset2")(1)="YesYes",
LookUpSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Record_Name.Value,"Dataset2")(1),
'if two records returned, check the HasIP field. If HasIP = YesNo, then use this combination second.
LookupSet(Fields!Main_ID.Value, Fields!Main_ID.Value, Fields!Record_Name.Value, "Dataset2").Length=2 AND
LookUpSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!HasIP.Value,"Dataset2")(0)="YesNo",
LookUpSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Record_Name.Value,"Dataset2")(0),
LookupSet(Fields!Main_ID.Value, Fields!Main_ID.Value, Fields!Record_Name.Value, "Dataset2").Length=2 AND
LookUpSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!HasIP.Value,"Dataset2")(1)="YesNo",
LookUpSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Record_Name.Value,"Dataset2")(1),
'If all else fails, display the number 2
True, 2)
I'm getting the correct one returned for 2 records, but getting #ERROR for zero and 1 records. If I break the formula down to their individual parts:
=SWITCH(
LookupSet(Fields!MainID.Value, Fields!MainID.Value, Fields!Record_Name.Value, "Dataset2").Length=0,
2)
This works. The number 2 is displayed in my report where the are no entries in Dataset2 (the field is blank for any other combination).
If I use:
=SWITCH(LookupSet(Fields!MainID.Value, Fields!MainID.Value, Fields!Record_Name.Value, "Dataset2").Length=1, LookUp(Fields!MainID.Value,Fields!MainID.Value,Fields!Record_Name.Value,"Dataset2"))
This works fine for when I have 1 record returned from Dataset2 (the field is blank for any other combination).
No matter what I tried with the third part (handling the 2 records), I'm getting issues. I can get the correct Record Name returned, but I'm getting #ERROR for 0 or 1 records.
I've tried nesting the third part in IIF statements, flipping it round to look at the length first, etc, but no success.
I cannot edit the underlying query of either dataset.
Any guidance much appreciated.
Solved
See:
SSRS 2012. Replicate grouping results in report in Query Designer
Essentially it was adding a numeric value to HasIP and also add in the Primary key of the second dataset.
Then sort the LookupSet array to get the value you want.
In the expression, you can use this to assign a default value, even when there are not results returned by the LookupSet:
=iif(
LookupSet(
Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Main_ID.Value,"Dataset2"
).Length>0,
Mid(
Split(
Join(
Code.JoinSorted(
LookupSet(
Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Q12b.Value,"Dataset2")
)
,";")
,";").GetValue(0)
, 'start point of mid
InStr(
Join(
Code.JoinSorted(
LookupSet(
Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Q12b.Value,"Dataset2"
)
)
,";")
,"$")
+1,
1),
"2"
)

SSRS mdx report: calculated member with maximum rank value for passes multivalue parameter

Here is a simple mdx query to MS OLAP cube, which outputs sale step stats for 3 cities with ranking of each sale stage, it works fine:
WITH
MEMBER [Measures].[rank] AS
case [Sales_step].currentmember.member_caption
when 'Contacts' then 1
when 'Clients' then 2
when 'Funded' then 3
else 0 end
SELECT {[Measures].[rank],
[Measures].[qnt]} ON COLUMNS,
NON EMPTY
crossjoin({[City].CHILDREN},
{[Sales_step].CHILDREN}) ON ROWS
FROM ( SELECT ( STRTOSET(#[Sales_step], CONSTRAINED) ) ON COLUMNS
FROM [SALES_PIPE])
The output is:
Now I want to build totals for each city without separate sale steps, but showing maximum archived sales stage rank only. The result must be:
I tried the following code to do that:
WITH
MEMBER [Measures].[rank max] AS
case [Sales_step].currentmember.member_caption
when 'Contacts' then 1
when 'Clients' then 2
when 'Funded' then 3
else 0 end
SELECT {[Measures].[rank max],
[Measures].[qnt]} ON COLUMNS,
NON EMPTY [City].CHILDREN ON ROWS
FROM ( SELECT ( STRTOSET(#[Sales_step], CONSTRAINED) ) ON COLUMNS
FROM [SALES_PIPE])
It does not generate error, but returns null values for calculated member [Measures].[rank max]:
It works only when I pass one value to #[Sales_step] parameter. While I need a multivalued param run. When I changed this snippet in case clause:
case [Sales_step].currentmember.member_caption
to:
case strtomember(#[Sales_step]).member_caption
it throwed an error "The STRTOMEMBER function expects a member expression for the 1 argument. A tuple set expression was used". Errors fire both for one- and multy-param when I use this too:
case strtoset(#[Sales_step]).currentmember.member_caption
How do I need to modify calculated member [Measures].[rank max] to get desired result with maximum rank for passed #[Sales_step] multivalue param?
I wonder if something like this works:
WITH
SET [S] AS
NonEmpty(
EXISTING [Sales_step].CHILDREN,
([City].CURRENTMEMBER, [Measures].[qnt]) //<<I think that [City].CURRENTMEMBER is probably redundant in this tuple
)
MEMBER [Mx] AS
CASE
WHEN INTERSECT([S], {[Sales_step].[Funded]}).COUNT = 1 THEN 3
WHEN INTERSECT([S], {[Sales_step].[Clients]}).COUNT = 1 THEN 2
WHEN INTERSECT([S], {[Sales_step].[Contacts]}).COUNT = 1 THEN 1
END
...
...

SQL: Sum returns null

So i have two tables academy_attempt & module_attempt
I am attempting to add two values from each of these tables together:
round(((select
sum(`academy_attempt`.`score`)
from
`academy_attempt`
where
((`academy_attempt`.`module_type_id` in (3 , 4, 5, 6))
and (`academy_attempt`.`user_id` = `U`.`id`))) + (select
sum(ifnull(`module_attempt`.`score`, 0))
from
`module_attempt`
where
((`module_attempt`.`module_type_id` in (3 , 4, 5, 6))
and (`module_attempt`.`user_id` = `U`.`id`)))),
2) AS `total_score`
in academy_attempt the where statement is met and in one row it returns the right amount (if it is alone) however module_attempt does not have any values that matches the where statement and therefor returns null.
Sadly this does not turn into 0 and since im guessing you can't do the operation: 17 + null = 17 it instead returns null.
To counter this i have attempt an IFNULL statement as you can see above but sadly this did not fix the problem
You have to apply the IFNULL() higher up, because an empty result set is considered to be null:
SELECT (...
) + IFNULL((SELECT SUM(`module_attempt`.`score`) ...), 0) AS total_score
NULL represents an unknown value, so naturally trying to add an unknown value to a number still results in an unknown value, albeit a different unknown value (hence NULL != NULL)
I think you actually want the COALESCE function, which returns the first non-null argument. Thus, you can wrap your null value with this function, and sum it as normal. COALESCE( NULL, 0 ) will return 0, and COALESCE(1,0) will return 1
https://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_coalesce

SUM of each row is counting null values as 0. How do I make mysql skip null values?

Well, the values aren't null per say, they are in VARCHAR(30) but in decimal form. However some of the records have "NA" in some fields. I would like mysql to skip those rows in SUM calculation when "NA" is present in the fields used for the SUM. Mysql is treating all incalculable fields as 0. The 0 from fields containing "NA" is misleading. I am doing a GROUP BY TABLE.ID.
Edit:
SELECT
SUM(
CASE
WHEN X >1 THEN 1
WHEN X<-1 THEN 2
ELSE 3
END
CASE
WHEN Y >1 THEN 1
WHEN Y <-1 THEN 2
ELSE 3
END)
AS "Col X+Y";
FROM TableA
GROUP BY TableA_ID;
Sometimes X and/or Y = "NA" on certain fields. I get 6 if both X and Y on TableA_ID = 17 or other numbers when one of them is "NA".
Edit (quoting my comment on VARCHAR):
"I tried storing my values as DEC(5,2), but some of the data from Excel have NA's in the fields. I did set X DEC(5,2) NULL and tried inserting NA into it but kept getting an error (cannot be null). I also tried making the default value "NA" but still get an error (cannot be null). I'll add in a sample query as edit."
I got it. I added in another WHERE clause using
WHERE ..... AND(Colx IS NOT NULL OR Coly IS NOT NULL OR ......);
I switched back the values to DEC(3,1) and made the fields NULLable with defaults null if the field value is NULL. I had to understand how to use NULL. I took out the 'NA's in Excel and left those field values blank.
if foo1 is null or NA just sum it as zero (the neutrum value in the addition), otherwise sum the value.
select sum( case when foo1 is null or foo1 = 'NA' then 0 else foo1 end) as sum, foo2
from FooTable group by foo2
or
select sum(foo1) from FooTable
where (foo2 <> 'NA' and foo2 is null) and (foo3 <> 'NA' or foo3 is null )
group by foo4