SSRS dynamic group expression needs to be null if a parameter is null - dynamic

I have an SSRS report that I am doing dynamic grouping on. Regular grouping on a field name that is provided through a report parameter is working with no problems.
The problem that I am having is that I want to avoid the grouping if the parameter is null.
I tried what this article suggested to use (checking for null in the IIF statement) but it isn't working for me:
http://www.optimusbi.com/2012/10/12/dynamic-grouping-ssrs/
NOT WORKING:
Setting GROUP_3 report parameter to NULL and checking for null in the grouping expression.
=IIF(Parameters!GROUP_3.Value is Nothing,1,Fields(Parameters!GROUP_3.Value).Value)
Result:
The IIF expression doesn't seem to be evaluating the null value properly. I get this as the result...
The Group expression for the grouping ‘GROUP_3’ contains an error: The
expression references the field '', which does not exist in the Fields
collection. 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.
(rsRuntimeErrorInExpression)
I also tried setting the parameter to 'blank' and this but I get the same error message.
=IIF(Parameters!GROUP_3.Value = "",1,Fields(Parameters!GROUP_3.Value).Value)
Is there something I am doing wrong here? Any suggestions?

The Iif() call evaluates all parameters passed to it. So when GROUP_3 doesn't have a value, you're trying to reference a non-existent member of the Fields collection in the third parameter of Iif().
It's possible (though ugly) to work around this with another embedded IIF() thusly:
IIF(Parameters!GROUP_3.Value is Nothing,1,Fields(IIF(Parameters!GROUP_3.Value is Nothing,"VALID COLUMN NAME",Parameters!GROUP_3.Value)).Value)
In case it isn't obvious, you need to replace "VALID COLUMN NAME" with a column name from your dataset. Doesn't matter which column it is as long as it's always in the dataset. This means if GROUP_3 is nothing it's using a valid column name reference in parameter three just to get around the error. The IIF() call will still default it to '1' and the code should behave as you desire.

Related

REPLACE NULL IN SSIS Derived Column

I have an SSIS package which transfers data from SAS to SQL Server. I'm creating a derived column but cannot get the REPLACENULL feature to work. I am receiving the error
"Invalid character value for cast specification"
which I am sure is because of NULL values in the source. Here is my current derived column expression:
REPLACENULL(DATEADD("d",(DT_I8)AuthEndDate,(DT_DATE)"1960-01-01"),0)
The REPLACENULL function isn't working here. Any way that this can be done? I am using SSIS 2008. Thanks.
Since you want blank/0 to flow downstream you need an if, not a replacenull()
Please note blank/0 in SQL Server writes as 1900-01-01, blank/0 are not valid date values, so it defaults to this. The only other option is NULL.
This should work if the destination is a datetime column:
ISNULL(AuthEndDate) ? (DT_DATE)0 : DATEADD("d",(DT_I8)AuthEndDate,(DT_DATE)"1960-01-01")
If you opt to write NULL instead of 1900-01-01, you can do this:
ISNULL(AuthEndDate) ? NULL(DT_DATE) : DATEADD("d",(DT_I8)AuthEndDate,(DT_DATE)"1960-01-01")
You must use one of the following expressions:
DATEADD("d",(DT_I8)REPLACENULL([AuthEndDate],0),(DT_DATE)"1960-01-01")
OR
ISNULL([AuthEndDate]) ? (DT_DATE)"1960-01-01" : DATEADD("d",(DT_I8)AuthEndDate,(DT_DATE)"1960-01-01")
Note that you cannot use a logic that can return multiple datatypes, both cases must return on datatype (DT_DATE)
If the source is returning NULLs, then try a REPLACENULL at AuthEndDate rather than after the calculations. The statement you have will try to do calculations with NULLs which is never good.
So...
REPLACENULL(DATEADD("d",REPLACENULL((DT_I8)AuthEndDate,0),(DT_DATE)"1960-01-01"),0)
Edit - replacenull and then apply conversion:
DATEADD("d",(DT_I8)REPLACENULL(AuthEndDate,0),(DT_DATE)"1960-01-01")
You won't need the first REPLACENULL anymore since we now handle it before the calculations.
Therefore:
DATEADD("d",REPLACENULL((DT_I8)AuthEndDate,0),(DT_DATE)"1960-01-01")
Edit: You can change the 0 to whatever you want the NULL to become, 0 was a placeholder.

Column sorting in SSRS report

I want to sort my column numbers at report level in SSRS instead of my query as I have some other columns sorted at query level and doing both sorts at query level don't work well. At the moment I get Columns order like 1, 10,2,3,4,5,6 instead of 1,2,3,4,5,6...10.
Once sorting is done I also want to add 'sales_' to the column name so I see sales_1, sales_2, sales_3 and so on. I understand this could be pretty straightforward but I'm new to SSRS. Thanks in advance.
The sort you are describing (1, 10,2,3,4) is a string sort, you need to convert the data type on that column to a numeric (in this case integer) type so that the sort is correct.
There are two solutions to this, you can add a calculated field to the record set, this can be helpful if you need to use this column multiple times, or you can simply use an expression for the sort order.
Right click on your dataset and select Add Calculated field, a dialog will open with all the column definitions for the query, here you can add your own custom fields.
For a custom field you will need an expression, which was the other options originally, so lets have a look at that component.
Edit the sort definition for the Tablix or group and select the field you want to sort on, to sort the way you would like the value needs to be numeric, we can use the CInt function to convert a value to an integer
NOTE: when using expressions to convert data types, if your data might not be convertible you may need to validate the value before conversion otherwise your
report execution will fail. The error messages are pretty helpful though and the expression dialog shows available functions an examples of usage for each of them.
For your second issue, use an expression in the field where you are displaying the data to concatenate the values, you can use the String.Format function or you can use simple string addition:
Expression Examples:
="sales_" + Fields!ItemValue.Value
="sales_" & Fields!ItemValue.Value
=String.Format("sales_{0}", Fields!ItemValue.Value)
I hope this helps you on your way, welcome to SSRS!

SSRS IIF Statement showing #Error when value is non numeric

I have a value that will either be a decimal or string. Sample
0.41
0.91
"0 / 2"
0.75
My current expression is
=IIF(IsNumeric(Fields!currentRate.Value), Format(CDBL(Fields!currentRate.Value), "P2"), Fields!currentRate.Value)
This properly returns the decimals formatted as a percentage, however the strings are only showing #Error. I've tried messing with various logic in the IIF statement and using a Switch instead. However the decimals always properly show as a percent, while the string only shows #Error.
Is it possible to display both numeric and string values in the same column while maintaining formatting on the numeric value?
The error relates to the CDbl function throwing an exception when trying to convert columns that are strings to a number. Yes, I know you're checking if it is numeric first but IIF is not a language construct, it is a function and as a function it evaluates all its parameters before passing them to the function. This means that both the True and False parameters get calculated even though one will be discarded and when it calculates CDbl on a string it throws an error.
Try the Val function. It has the benefit of not throwing errors when it gets passed non-numeric data - it just does the best it can to convert it to a number.
=IIF(IsNumeric(Fields!currentRate.Value), Format(Val(Fields!currentRate.Value), "P2"), Fields!currentRate.Value)
For anyone else who stumbles upon this question. Changing my formatting from using CDBL to VAL allows this to work properly.
IIF() is a function in SQL Server. As such, it returns a value whose type is specified by its arguments. As explained in the documentation:
Returns the data type with the highest precedence from the types in
true_value and false_value. For more information, see Data Type
Precedence (Transact-SQL).
If one of the two values is a number, then that has precedence. The assumption is that both are numbers. In other words, an expression in SQL only returns one type for all rows.

MS-Access - why can't this update query fill empty cells?

In MS-Access database, table called NewTable3
colname is a text column containing lot of empty cells or blanks.
i want to put ? character in empty cells . when i run the query
UPDATE NewTable3 SET colname = '?' WHERE ISNULL(colname) ;
This query updates 0 records why . what is wrong with this query
Two quick things:
1) Try putting the colname in square brackets.
2) Remember that empty cells (Nulls) and empty strings ("") are different.
Together:
UPDATE NewTable3 SET [colname] = "?" WHERE ISNULL([colname]) OR [colname] = "";
Also, are you running the query in Access itself, or just using the Access engine and using the data in another program/via a VBA script? It can make a difference.
EDIT:
Based on #onedaywhen's prodding, I now see that I never fully absorbed the original question, which was asking about replacing Nulls with the literal ? character. This is insane and not helpful or useful. If you don't have a meaningful default value for the field, then LEAVE IT NULL. If you want to distinguish between Null (unknown) and Blank (i.e., known to be blank), you can allow zero-length strings and change the Nulls to ZLS.
My original post follows, since I think it is useful for people who might get to this crazy question needing to do things properly:
In total, all the answers in this thread end up solving all the problems with the original SQL statement, but they do so incompletely, so I'll compile them all together in an attempt to create a comprehensive correct answer.
#Wim Hollebrandse wisely points out that a parameter needs brackets, but posts the SQL as:
UPDATE NewTable3 SET colname = '[?]' WHERE ISNULL(colname);
This is incorrect, in that the quotes will cause what's inside them to be treated literally, instead of evaluated as a paramter, so you'll end up with all your fields updated to the literal value "[?]". The correct syntax would be:
UPDATE NewTable3 SET colname = [?] WHERE ISNULL(colname);
#GuinnessFan points out a problem in the WHERE clause, suggesting out that the result of IsNull() needs to be compared to True in order for the WHERE clause to work. In other words, this:
WHERE IsNull(NewTable3.colname)
...should be this:
WHERE IsNull(NewTable3.colname)=True
But given that both statements evaluate the same, they are entirely equivalent. But #GuinnessFan is correct that this is the best syntax:
WHERE NewTable3.colname Is Null
#mavnn points out that the fields may be "empty" while not being Null, which is a very common problem. I believe on principle (and consistent with my understanding of the official SQL standards) that fields should be initialized as Null and should not allow zero-length strings. It is certainly possible in some applications that one might want to distinguish Null, i.e., value not yet supplied, from blank (zero-length string), i.e., value known to be blank. But if that's part of the application design, then the user should know that criteria on such fields need to consider whether one or both should be included (i.e., both Null and <>"" or one or the other).
From my point of view, it was unfortunate that the the old default for text fields (where AllowZLS defaulted to FALSE) was changed in Access 2003 to allow ZLS's by default. This means that many people who don't notice that AllowZLS is set to TRUE when they create their tables end up with ZLS's stored in their text fields without intending to do so (and importing a table from a previous version also defaults to TRUE).
While testing for Null and ="" will make the WHERE clause that is seeking all "empty" fields work as expected, the permanent fix is to change the field definition to disallow ZLS's. But do note that changing AllowZLS to FALSE does not clear the existing ZLS's -- you have to run a SQL UPDATE to remove them.
Last of all, in using parameters, it is better to declare them such that the values that the user can input are restricted to appropriate values. If the field is numeric, you to limit it to numeric values, if a date, date values, if text or memo, to text:
PARAMETERS [User Prompt] Long;
UPDATE MyTable SET LongIntegerColumn = [User Prompt]
PARAMETERS [User Prompt] DateTime;
UPDATE MyTable SET DateColumn = [User Prompt]
PARAMETERS [User Prompt] Text ( 255 );
UPDATE MyTable SET TextColumn = [User Prompt]
Note that with Text(255) as your parameter type, anything supplied by the user is truncated to 255 characters, even if it's longer than that (it would be a pretty unusual situation where'd you'd need that). For values longer than that (such as memo fields), you omit the text length declaration:
PARAMETERS [User Prompt] Text;
UPDATE MyTable SET TextColumn = [User Prompt]
In any event, I think so-called anonymous parameters are not too helpful, as you aren't leveraging the power of parameters to restrict data type of input criteria.
Try:
UPDATE NewTable3 SET colname = '[?]' WHERE ISNULL(colname);
The questionmark is used for anonymous parameters, so you need to escape it as above. Note that I have not tried this.
UPDATE NewTable3 SET NewTable3.colname = "?"
WHERE (((NewTable3.colname) Is Null));
To keep your function: WHERE (((IsNull([NewTable3.colname]))=True));
I don't believe that replacing the NULL value with your own 'magic' value ? will cause you anything but further pain.
Here's hoping you may draw inspiration from this article:
How To Handle Missing Information Without Using (some magic value)

TSQL: No value instead of Null

Due to a weird request, I can't put null in a database if there is no value. I'm wondering what can I put in the store procedure for nothing instead of null.
For example:
insert into blah (blah1) values (null)
Is there something like nothing or empty for "blah1" instead using null?
I would push back on this bizarre request. That's exactly what NULL is for in SQL, to denote a missing or inapplicable value in a column.
Is the requester experiencing grief over SQL logic with NULL?
edit: Okay, I've read your reply with the extra detail about this job assignment (btw, generally you should edit your original question instead of posting more information in an answer).
You'll have to declare all columns as NOT NULL and designate a special value in the domain of that column's data type to signify "no value." The appropriate value to choose might be different on a case by case basis, i.e. zero may signify nothing in a person_age column, but it might have significance in an items_in_stock column.
You should document the no-value value for each column. But I suppose they don't believe in documentation either. :-(
Depends on the data type of the column. For numbers (integers, etc) it could be zero (0) but if varchar then it can be an empty string ("").
I agree with other responses that NULL is best suited for this because it transcends all data types denoting the absence of a value. Therefore, zero and empty string might serve as a workaround/hack but they are fundamentally still actual values themselves that might have business domain meaning other than "not a value".
(If only the SQL language supported a "Not Applicable" (N/A) value type that would serve as an alternative to NULL...)
Is null is a valid value for whatever you're storing?
Use a sentry value like INT32.MaxValue, empty string, or "XXXXXXXXXX" and assume it will never be a legitimate value
Add a bit column 'Exists' that you populate with true at the same time you insert.
Edit: But yeah, I'll agree with the other answers that trying to change the requirements might be better than trying to solve the problem.
If you're using a varchar or equivalent field, then use the empty string.
If you're using a numeric field such as int then you'll have to force the user to enter data, else come up with a value that means NULL.
I don't envy you your situation.
There's a difference between NULLs as assigned values (e.g. inserted into a column), and NULLs as a SQL artifact (as for a field in a missing record for an OUTER JOIN. Which might be a foreign concept to these users. Lots of people use Access, or any database, just to maintain single-table lists.) I wouldn't be surprised if naive users would prefer to use an alternative for assignments; and though repugnant, it should work ok. Just let them use whatever they want.
There is some validity to the requirement to not use NULL values. NULL values can cause a lot of headache when they are in a field that will be included in a JOIN or a WHERE clause or in a field that will be aggregated.
Some SQL implementations (such as MSSQL) disallow NULLable fields to be included in indexes.
MSSQL especially behaves in unexpected ways when NULL is evaluated for equality. Does a NULL value in a PaymentDue field mean the same as zero when we search for records that are up to date? What if we have names in a table and somebody has no middle name. It is conceivable that either an empty string or a NULL could be stored, but how do we then get a comprehensive list of people that have no middle name?
In general I prefer to avoid NULL values. If you cannot represent what you want to store using either a number (including zero) or a string (including the empty string as mentioned before) then you should probably look closer into what you are trying to store. Perhaps you are trying to communicate more than one piece of data in a single field.