CELL Calculation with dynamic mdx expression - ssas

I've been trying for a while to create a (little bit complicated?) cell calculation where I need to use a dynamic formula but is not working. At the end I'm obtaining the mdx expression as the cell value, which is wrong. Here is my expression:
-----------------------------------------------------------------------
---SET With 2 elements(Sales Fcst(20131223), Sales Fcst(2014))
WITH SET [CategoryFcst] AS
FILTER([Category].[Category].children, InStr([Category].[Category].CURRENTMEMBER.MEMBER_CAPTION,"Sales Fcst") > 0 )
CELL CALCULATION SalesPlanAch FOR
'([Category].[Category].[Sales Plan Att%], [Measures].[Amount])'
AS
'(StrToMember("' + [CategoryFcst].item(0).UNIQUENAME + '"),[Measures].[Amount] )'
--The formula expression result is: (StrToMember("[Category].[Category].&[29]"),[Measures].[Amount] )
SELECT [Time].[Calendar Time].[Quarter].members on columns,
[Category].[Category].children on rows
from [AllData]
WHERE ([Measures].[Amount])
-----------------------------------------------------------------------
If I put directly '(StrToMember("[Category].[Category].&[29]"),[Measures].[Amount])' as the cell calculation formula it will work, but I need to calculate that dynamically.
Also, if I put '(StrToMember("' + '[Category].[Category].&[29]' + '"),[Measures].[Amount] )' doesn't work. It sets that string as the cell value.
That is not the real cell calculation but the part that is causing me problems.
I'd appreciate any advice/answers.
Best regards,
Daniel

Just use
'(StrToMember([CategoryFcst].item(0).UNIQUENAME),[Measures].[Amount] )'
As far as I understand, the necessity of quotes around this expression is due to the history of Analysis Services as described here. And, as described in the same article, in version 2005 of Analysis Services, this was changed for member and set definitions in the WITH clause, but apparently not for the rarely used cell calculations. Hence, the quotes here are not something that encloses a string, but more or less a syntax requirement to enclose the expression.
I am actually not sure how you would use single quotes within this expression. But you can use double or single quotes in MDX expressions to enclose strings. Thus you will rarely come across the necessity to absolutely need single quotes in this type of expressions.

Related

Escaping single quotes in the PLACEHOLDER clause of a HANA SQL statement

I noticed an inconsistency in how "HANA SQL" escapes single quotes in the context of the PLACEHOLDER clause. For example, consider the following PLACEHOLDER clause snippet:
('PLACEHOLDER' = ('$$CC_PARAM$$','''foo'',''an escaped single quote \'' '''))
The PLACEHOLDER clause above contains multiple values assigned to the CC_PARAM. parameter. We can see that inside of the second argument we have a single quote that's escaped with a backslash. However, we escape the single quotes outside each argument with another single quote (i.e. we do '' instead of \''. It's possible to use the \'' format for the first case, but it's not possible to use the '' format in the second case.
Why is there this discrepancy? It makes escaping quotes in multi-input input parameters tricky. I'm looking to programmatically craft SQL queries for HANA. Am I missing something here? Is it safe to use \'' over '' in all cases? Or do I need logic that can tell where a single quote occurs and escape as appropriate?
The implicit rule here - given by how the software is implemented - is that for parameter values of calculation views, the backslash \ is used to escape the single quotation mark.
For all standard SQL string occurrences, using the single-quotation mark twice '' is the correct way to differentiate between syntax element and string literal.
As for the why:
the PLACEHOLDER syntax is not SQL, but a HANA-specific command extension. So, there is no general standard that the current implementation violates.
that given, this command extension is embedded into, respectively clamped onto the standard SQL syntax and has to be handled by the same parser.
But the parameters are not only parsed once, by the SQL parser but again by the component that instantiates the calculation scenario based on the calculation view. With a bit of squinting it's not hard to see that the parameters interface is a general key-value interface that allows for all sorts of information to be handed over to the calc. engine.
One might argue that the whole approach of providing parameters via key-value pairs is not consistent with the general SQL syntax approach and be correct. On the flip side, this approach allows for general flexibility for adding new command elements to the HANA-specific parts, without structurally changing the syntax (and with it the parser).
The clear downside of this is that both the key names, as well as the values, are string-typed. To avoid losing the required escaping for the "inner string" an escape string different from the main SQL escape string needs to be used.
And here we are with two different ways of handing over a string value to be used as a filter condition.
Funny enough, both approaches may still lead to the same query execution plan.
As a matter of fact, in many scenarios with input parameters, the string value will be internally converted into a SQL conforming form. This is the case when the input parameter is used for filtering or in expressions in the calc. view that can be converted into SQL expressions.
For example
SELECT
"AAA"
FROM "_SYS_BIC"."sp/ESC"
('PLACEHOLDER' = ('$$IP_TEST$$', 'this is a test\''s test'));
shows the following execution plan on my system
OPERATOR_NAME OPERATOR_DETAILS
PROJECT TEST.AAA
COLUMN TABLE FILTER CONDITION: TEST.AAA = 'this is a test's test'
(DETAIL: ([SCAN] TEST.AAA = 'this is a test's test'))
Note how the escape-\' has been removed.
All in all: when using PLACEHOLDER values, the \' escaping needs to be used and in all other cases, the '' escaping.
That should not be terribly difficult to implement for a query builder as you can consider this when dealing with the PLACEHOLDER syntax.

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!

SQL string comparison -how to ignore blank spaces

I have prepared an SQL query that I will have to run on several databases (Oracle and Sybase) where some data might be stored differently.
I have noticed that one of the differences in data storage is the blank string.
For example, in the column PRODUCT_TYPE below, please have a look at the second record:
This "empty string" (the data type is CHAR(15)) circled in red is equal to '' in some of the databases, whereas it's equal to ' ' to some others. The length is never constant and there are several fields that behave as such.
So, since I need to filter on these "empty strings", I should change the following statement in my WHERE clause:
WHERE PRODUCT_TYPE = ''
...because the above will take the ' ' string as different than '' even if "functionally" speaking is not.
I would hence like to make the statement in a way that it "ignores white spaces", i.e. ' ' is equal to '' that is equal to ' ' etc.
How should I do this change in order to make it work?
I have tried the simple replacing approach:
WHERE REPLACE(PRODUCT_TYPE,' ','') = ''
...but it doesn't seem to work, probably because I should use a different character.
For sake of testing, inside the ' below there is a copied-pasted example of what I find in these "empty strings":
' '
Ideally, it should be a "non-specific SQL" solution since I will have to run the same query on both Oracle and Sybase RDBMS. Any idea?
You can use trim on the column.
where trim(product_type) is null
The above is not DBMS-independent, since Sybase does not provide the trim function.
However, the below approach will work both in Sybase and Oracle:
where rtrim(ltrim(product_type)) is null
You can use the replace statement you've tried but you should test for "is null" instead of =''
WHERE REPLACE(PRODUCT_TYPE,' ','') is null
See also:
null vs empty string in Oracle
The simple (and non-DBMS specific) answer is:
Do not use CHAR(15).
char(n) is a fixed length data type. So no matter what you store in there, the value will always be padded to the defined length. If you store a single character, the DBMS will store that single character and 14 spaces.
Change your columns to use varchar(15) and you should not have any problems.

Excel 2007 (Conditional Formatting) AND & IF

I hope you can help me on this issue.
I am currently using Excel 2007 and I am creating a dynamic Planning/Time Sheet for our Team.
So far everything is going well.
Now unfortunately I am having an issue with the Conditional Format.
I am formatting the Cells in order to graphically show the current Status of the Person working. I am using the Conditional Format with a Formula example: =OFFSET(DataStart17D;COLUMN();ROW()-49;1;1)="PM"
Now I am trying to applying 2 conditions with a gradient fill of 2 colors like example: =AND(IF(OFFSET(DataStart17D;COLUMN();ROW()-49;1;1)="PM";TRUE;FALSE);IF(OFFSET(DataStart17D;COLUMN();ROW()-52;1;1)="AM";TRUE;FALSE)
Problem is, as soon as I use the IF or the AND Statement no condition is applied at all.
I have applied the above formula to the Cell itself and have received "TRUE" as the condition.
What is odd too is that if I apply =OFFSET(DataStart17D;COLUMN();ROW()-49;1;1)="PM" it works fine, if I use =IF(OFFSET(DataStart17D;COLUMN();ROW()-49;1;1)="PM";TRUE;FALSE) once again no condition applies.
I have searched the web for a Solution and could not find one yet :(
Would really be pleased if someone could help me on this one :)
Best Regards,
Richard J. Dana
You don't need IF Statment and TRUEs and FALSEs withih a Conditional Formatting formula. By its nature the formula is conditional.
Try something like:
=AND(OFFSET(DataStart17D;COLUMN();ROW()-49;1;1)="PM";OFFSET(DataStart17D;COLUMN();ROW()-49;1;1)="AM")
Once you do so, you'll see an additional problem. The two statements in your AND function are mutually exclusive, so it will never evaluate to TRUE.
EDIT:
There does seem to be an issue with the AND statement and multiple OFFSET statements that use ROW or COLUMN
Please note that I'm going to use commas instead of semicolons as function parameter separators here, otherwise it's too hard to convert. You'll have to change the commas back to semicolons.
Also note that you didn't need the last two arguments in either the ROW or COLUMN function in your original question. You had them set to a height and width of 1, which is the default, and is optional.
Here's a simplified example:
If you do something like:
OFFSET(DataStart17D,ROW()+1,COLUMNS())="PM"
it will evaluate to TRUE in the worksheet and also in the conditional formatting
If you do something like:
=AND(OFFSET(DataStart17D,ROW()+1,COLUMNS())="PM",OFFSET(DataStart17D,ROW()+1,COLUMNS())="PM")
which is just repeating the same statement twice, it will evaluate to TRUE in the worksheet, but won't trigger the conditional format.
All of the above is just as you stated in your question. The answer that I think works is to use ROWS and COLUMNS instead, like this:
=AND(OFFSET(DataStart17D,ROWS($1:2)+1,COLUMNS($A:A))="PM",OFFSET(DataStart17D,ROWS($1:2)+1,COLUMNS($A:A))="AM")
The above would be the formula for A2. Note that the first row or column inside the parentheses is anchored with a dollar sign. This gives you the count of rows or columns from A1, effectively the same thing as the ROW or COLUMN function.

Preg_replace solution for prepared statements

I have a command class that abstracts almost all specific database functions (We have the exactly same application running on Mssql 2005 (using ODBC and the native mssql library), MySQL and Oracle. But sometimes we had some problems with our prepare method that, when executed, replaces all placeholders with their respective values. But the problem is that I am using the following:
if(is_array($Parameter['Value']))
{
$Statement = str_ireplace(':'.$Name, implode(', ', $this->Adapter->QuoteValue($Parameter['Value'])), $Statement);
}
else
{
$Statement = str_ireplace(':'.$Name, $this->Adapter->QuoteValue($Parameter['Value']), $Statement);
}
The problem arises when we have two or mer similar parameters names, for example, session_browser and session_browse_version... The first one will partially replace the last one.
Course we learned to go around specifying the parameters within a specific order, but now that I have some "free" time I want to make it better, so I am thinking on switching to preg_replace... and I am not good in regular expression, can anyone give any help with a regex to replace a string like ':parameter_name`?
Best Regards,
Bruno B B Magalhaes
You should use the \b metacharacter to match the word boundary, so you don't accidentally match a short parameter name within a longer parameter name.
Also, you don't need to special-case arrays if you coerce a scalar Value to an array of one entry:
preg_replace("/:$Name\b/",
implode(",", $this->Adapter->QuoteValue( (array) $Parameter['Value'] )),
$Statement);
Note, however, that this can make false positive matches when an identifier or a string literal contains a pattern that looks like a parameter placeholder:
SELECT * FROM ":Name";
SELECT * FROM Table WHERE column = ':Name';
This gets even more complicated when quoted identifiers and string literals can contain escaped quotes.
SELECT * FROM Table WHERE column = 'word\':Name';
You might want to reconsider interpolating variables into SQL strings during prepare, because you're defeating any benefits of prepared statements with respect to security or performance.
I understand why you're doing what you're doing, because not all RDBMS back-end supports named parameters, and also SQL parameters can't be used for lists of values in an IN() predicate. But you're creating an awfully leaky abstraction.