MDX Conditional/Dynamic Case Statement based on SSRS tuple parameter - reporting-services

Is it possible to build a case statement (or equivalent) in MDX query to group together dimensional members based on parameter input from SSRS?
Below is a query showing roughly what I am trying to achieve (parameters have been commented out and hardcoded for testing) I'm afraid that I'm fairly new to mdx;
WITH
--PERIOD FOR COMPARISON BLOCK
SET [MonthNumber] AS
(
STRTOSET("[Date Procurement Created].[Month Number].&[9]"
--#DimCalendarMonthNumber
, CONSTRAINED)
)
--CONDITIONAL CASE BLOCK
SET [SelectedSuppliers] AS
CASE [Dim Supplier].[Supplier Name].CurrentMember
WHEN STRTOSET("[Dim Supplier].[Supplier Name].&[Flannels Direct Co Ltd],[Dim Supplier].[Supplier Name].&[Zucchini Trading Co]"
--#DimSupplierSupplierName
, CONSTRAINED)
THEN [Dim Supplier].[Supplier Name].CurrentMember
ELSE 'Other'
END
--CURRENT PERIOD BLOCK
MEMBER [Measures].[CP_LineTotal]
AS SUM(
([Measures].[Line Total],[MonthNumber])
), FORMAT_STRING = 'Currency'
--MAIN QUERY BLOCK
SELECT {
[Measures].[Line Total]
, [Measures].[CP_LineTotal]
}
ON 0,
NON EMPTY (
[SelectedSuppliers]
*[Dim Supplier].[AC Number].[AC Number].MEMBERS
*[Date Procurement Created].[Year Name].[Year Name].MEMBERS
)
ON 1
FROM
[TRANSACTION_PROCUREMENT]

I think this part of your code could change to the following:
SET [SelectedSuppliers] AS
IIF(
[Dim Supplier].[Supplier Name].CurrentMember
IS [Dim Supplier].[Supplier Name].&[Flannels Direct Co Ltd],[Dim Supplier].[Supplier Name].&[Zucchini Trading Co]
,[Dim Supplier].[Supplier Name].CurrentMember
,'Other'
)
IIF should always be used rather than CASE if possible.
Use the IS operator to compare members.
Also no need to use Sum in your definition of the measure as a simple tuple will suffice:
MEMBER [Measures].[CP_LineTotal] AS
([Measures].[Line Total],[MonthNumber])
, FORMAT_STRING = 'Currency'

Related

SSRS 2008 R2 - all parameters multi value AND optional

I've got a report that has 6 parameters. All parameters need to be optional and 3 have to be multi-value. One of the optional parameters is a dropdown, the rest are manually keyed in text boxes.
The Where clause below works when there are multiple #VendorNum values and one #FullJA value, but fails with multiple #FullJA values regardless of the #VendorNum count.
Parameters:
#VendorNum - keyed manually by user (space delimited) - optional, can be multivalue
#FullJA - keyed manually by user (space delimited) - optional, can be multivalue
#BU - optional, can be multivalue - when #JA is populated, this will auto-populate, if #JA isn't populated it's a dropdown with all selected.
#JA3 - keyed by user - optional, single value
#StartDate and #EndDate - optional single values
select * from some_table
WHERE
/*FULL JA*/
(
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND LEFT(JA, 7) IN (#FullJA)
AND BU IN(#BU)
AND #JA3 IS NULL
)
OR
/*DATE RANGE*/
(
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND LEN(ISNULL(CONVERT(VARCHAR(20), Cleared_When), '0')) >= #ClearedOnly
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND BU IN (#BU)
AND #FullJA IS NULL
AND #JA3 IS NULL
)
/*BUS UNIT AND JA3*/
OR (
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND BU IN (#BU)
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND LEFT(JA, 3) = (#JA3)
AND #FullJA IS NULL
)
/*BUS UNIT ONLY*/
OR (
SUBSTRING(VendorNum, PATINDEX('%[^0]%', VendorNum + '.'), LEN(VendorNum)
) IN (#VendorNum)
AND BU IN (#BU)
AND ad.Audit_Publish_Date >= ISNULL(#StartDate, '2015-01-01')
AND ad.Audit_Publish_Date <= ISNULL(#EndDate, '2025-12-31')
AND #JA3 IS NULL
AND #FullJA IS NULL
)
The dataset parameter values for #FullJA and #VendorNum are both
=IIF(InStr(Parameters!FullJA.Value," ")>0,SPLIT(Parameters!FullJA.Value," "),Parameters!FullJA.Value) and all params are set as NOT multivalue, with nulls allowed.
Any help would be greatly appreciated. I've written over 200 reports for this project and this is the only one that is really grinding my gears!
Thanks!
I would approach this by building up some temp tables / table variables, to hold the potentially multi-valued variables, and then joining to those tables. This has the advantage of you being able to insert all possible values, in the case they have omitted the variable. So, you'd split your strings and put them into those tables (something along the lines of this example) if given the variable, and otherwise just do an insert into to populate your temp table / table variable.
For a split function, I prefer something like this:
create FUNCTION [dbo].[Split] (#sep VARCHAR(32), #s VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
(
SELECT r.value('.','VARCHAR(MAX)') as Item
FROM (SELECT CONVERT(XML, N'<root><r>' + REPLACE(REPLACE(REPLACE(#s,'& ','& '),'<','<'), #sep, '</r><r>') + '</r></root>') as valxml) x
CROSS APPLY x.valxml.nodes('//root/r') AS RECORDS(r)
)
GO
GRANT SELECT
ON OBJECT::[dbo].[Split] TO PUBLIC
AS [dbo];
I would then put those variables into a table using something like this (my separator is a ", "):
select ltrim(rtrim(ppl.Item)) as PersonName
into #gppl
from dbo.Split(', ', #PersonListForCompare) as ppl
You would do something more like:
select ltrim(rtrim(vnd.Item)) as VendorNum
into #vendorNums
from dbo.Split(', ', #VendorNum) as vnd
You would then join to that temp table just like any other table & use it to limit your results that way. In your case, you want to put in all vendors (possibly) if they didn't give you any input. So, you'd do something like:
create table #vendorNums (VendorName varchar(64)) --I have no idea, here, what this data looks like
if #VendorNum is not null and datalength(#VendorNum) > 0
insert into into #vendorNums (VendorNum)
select ltrim(rtrim(vnd.Item))
from dbo.Split(', ', #VendorNum) as vnd
else
insert into into #vendorNums (VendorNum)
select VendorNum
from dbo.Vendors
That said, I think that you could use your select from dbo.Split directly as a table in a join, rather than putting it into the temp table. Only problem would be you'd have to be sure you had data in there to split, or else you're going to have a bunch of combinations to get the right match-up of null parameters vs. filled ones.

SSRS The restrictions imposed by the CONSTRAINED flag in the STRTOSET function were violated

I got a problem using Multi-Value Parameters in SSRS.
I got a DataSet with this MDX Query :
SELECT NON EMPTY { [Measures].[Air Temperature Out - Fact Germination
Continue] } ON COLUMNS, NON EMPTY { ([81 Germination Continue].[Batch
Number].[Batch Number].ALLMEMBERS * [80 Germination General].[Plant
Name].[Plant Name].ALLMEMBERS * [80 Germination General].[Production
Unit].[Production Unit].ALLMEMBERS * [81 Germination
Continue].[Characteristic Date].[Characteristic Date].ALLMEMBERS * [80
Germination General].[Start Date Unloading].[Start Date
Unloading].ALLMEMBERS * [80 Germination General].[Start Date].[Start
Date].ALLMEMBERS * [80 Germination General].[End Date].[End
Date].ALLMEMBERS ) } DIMENSION PROPERTIES MEMBER_CAPTION,
MEMBER_UNIQUE_NAME ON ROWS FROM ( SELECT (
STRTOSET(#GerminationGeneralProductionUnit, CONSTRAINED) ) ON COLUMNS
FROM ( SELECT ( STRTOSET(#GerminationGeneralPlantName, CONSTRAINED) )
ON COLUMNS FROM ( SELECT ( STRTOSET(#GerminationContinueBatchNumber,
CONSTRAINED) ) ON COLUMNS FROM [Supervision]))) CELL PROPERTIES VALUE,
BACK_COLOR, FORE_COLOR, FORMATTED_VALUE, FORMAT_STRING, FONT_NAME,
FONT_SIZE, FONT_FLAGS
When running the report, I got the error :
The restrictions imposed by the CONSTRAINED flag in the STRTOSET
function were violated.
From my research, this means I have to put the full name in the parameters of the DataSet. The thing is that I think I did it, even if it's a bit different from what I saw, because of the construction of the datasets. For example, for the Germinaction Continue Batch Number, my parameter value is :
=Split(Replace(Join(Parameters!BatchNumbers.Value, ","), "[70 Steeping General]", "[81 Germination Continue]"), ",")
As you can guess, my data come from the dimension "[70 Steeping General]", which I try to put in the dimension "[81 Germination Continue]", the values are the same in both dimension ([81 Germination Continue].[Batch Number].[Batch Number] and [70 Steeping General].[Batch Number].[Batch Number]
Does the problem come from the fact that it's a multi-value parameter that looks like this? :
[81 Germination Continue].[Batch Number].[1234567890],
[81 Germination Continue].[Batch Number].[1234567891],
[81 Germination Continue].[Batch Number].[1234567892]
EDIT :
The parameters of the report :
FromSteepingStartDate
ToSteepingStartDate
Both are Date/Time parameters and have an available value set to None, Default Value is DateAdd("m", -1, Today()) and DateAdd("d", -2, Today())
They are used in the DataSet DataSteeping, and the value of the parameter is
="[70 Steeping General].[Start Day].&[" + CStr(Format(CDate(Parameters!FromSteepingGeneralStartDay.Value),
"yyyy-MM-dd"))+ "T00:00:00]"
SteepingGeneralPlantName
This parameter is a multi-value parameter, that initialy come from my dataset DataSteeping, so an autogenerated dataset has been created, with the following query :
WITH MEMBER [Measures].[ParameterCaption] AS [70 Steeping
General].[Plant Name].CURRENTMEMBER.MEMBER_CAPTION MEMBER
[Measures].[ParameterValue] AS [70 Steeping General].[Plant
Name].CURRENTMEMBER.UNIQUENAME MEMBER [Measures].[ParameterLevel] AS
[70 Steeping General].[Plant Name].CURRENTMEMBER.LEVEL.ORDINAL SELECT
{[Measures].[ParameterCaption], [Measures].[ParameterValue],
[Measures].[ParameterLevel]} ON COLUMNS , [70 Steeping
General].[Plant Name].ALLMEMBERS ON ROWS FROM [Supervision]
The dataset is filtered like Parameter.Level <> 0 and Parameter.Caption <> "Unknown"
This parameter is used in every other DataSet, but they don't all come from the same dimension, so the parameter value in the others datasets properties looks like this:
=Split(Replace(Join(Parameters!SteepingGeneralPlantName.Value, ","), "[70 Steeping General]", "[80 Germination General]"), ",")
SteepingGeneralProductionUnit
This parameter is a multi-value parameter too, that initialy come from my dataset DataSteeping, so an autogenerated dataset has been created, but I changed it, so now it doesn't come from my dimension [70 SteepingGeneral], but from [04 Productions Unit], which contains all the productions unit, and is compatible with all the other dimensions, so it was easier to load in the other datasets, the MDX query is :
WITH MEMBER [Measures].[ParameterCaption] AS [04 Production
Units].[Production Unit].CURRENTMEMBER.MEMBER_CAPTION MEMBER
[Measures].[ParameterValue] AS [04 Production Units].[Production
Unit].CURRENTMEMBER.UNIQUENAME MEMBER [Measures].[ParameterLevel] AS
[04 Production Units].[Production Unit].CURRENTMEMBER.LEVEL.ORDINAL
SELECT {[Measures].[ParameterCaption], [Measures].[ParameterValue],
[Measures].[ParameterLevel]} ON COLUMNS , [04 Production
Units].[Production Unit].ALLMEMBERS ON ROWS FROM ( SELECT (
STRTOSET(#PlantsPlant, CONSTRAINED) ) ON COLUMNS FROM [Supervision])
The dataset is filtered like Parameter.Level <> 0
This parameter is used in every other DataSet, only my Dataset DataGermination need an expression for this parameter, because it's from another dimension :
=Split(Replace(Join(Parameters!SteepingGeneralProductionUnit.Value, ","), "[04 Production Units]", "[80 Germination General]"), ",")
TempSteepingLimit
This parameter is not important for the problem, it's just the temperature limit, which I need to display the duration where the temperature is above this limit. It's a text parameter that I convert to a float (with a replace so the user can type "," or "."). It has no dataset and is used in no one, just in a textbox expression.
BatchNumbers
This hidden parameter is populated by a DataSet which return all the batch numbers that match with the other parameters (From/To Steeping Start Date, Plant Name and Production Unit).
They are used in 2 DataSet (DataGermination and DataBatchProcessData), because I couldn't add the Steeping Start Date in those datasets.
In DataGermination, the value for BatchNumber is :
=Split(Replace(Join(Parameters!BatchNumbers.Value, ","), "[70 Steeping General]", "[81 Germination Continue]"), ",")
The dataset that populate this parameter is not autogenerated, I just added it, with this query :
SELECT NON EMPTY { [Measures].[Barley Volume] } ON COLUMNS, NON EMPTY
{ ([70 Steeping General].[Batch Number].[Batch Number].ALLMEMBERS *
[70 Steeping General].[Plant Name].[Plant Name].ALLMEMBERS * [70
Steeping General].[Production Unit].[Production Unit].ALLMEMBERS * [65
Batch Process Data].[Steeping Start Date].[Steeping Start
Date].ALLMEMBERS ) } DIMENSION PROPERTIES MEMBER_CAPTION,
MEMBER_UNIQUE_NAME ON ROWS FROM ( SELECT (
STRTOMEMBER(#FromSteepingGeneralStartDay, CONSTRAINED) :
STRTOMEMBER(#ToSteepingGeneralStartDay, CONSTRAINED) ) ON COLUMNS FROM
( SELECT ( STRTOSET(#SteepingGeneralProductionUnit, CONSTRAINED) ) ON
COLUMNS FROM ( SELECT ( STRTOSET(#SteepingGeneralPlantName,
CONSTRAINED) ) ON COLUMNS FROM [Supervision]))) CELL PROPERTIES VALUE,
BACK_COLOR, FORE_COLOR, FORMATTED_VALUE, FORMAT_STRING, FONT_NAME,
FONT_SIZE, FONT_FLAGS
(Sorry for my english)
Don't hesitate to ask questions!
Thank's for your help! :)

Passing multiple values to SSRS using MDX

I am running the following command for getting a multi value report
StrToSet
("[Dim Branch].[HierarchyB-T-C].[Trading Code].&[" +
Replace(
Join(
Parameters!TradingName.Value,"],"
) +"]",",",",[Dim Branch].[HierarchyB-T-C].[Trading Code].&["),",")
But I'm getting an error
'The Syntax for 'Join' is incorrect'.
I don't know what I am doing wrong. Can anyone correct me please?
If I change it to StrToSet(#TradingName, Constrained) it works for single value, but I'd like to pass multiple values.
Do you need curly braces to form a set? I have added one at the start of the below ... a little unsure where the end of your string is - does it end like this .&["?!
StrToSet(
"{[Dim Branch].[HierarchyB-T-C].[Trading Code].&["
+
Replace(
Join(Parameters!TradingName.Value,"],") + "]"
, ","
, ",[Dim Branch].[HierarchyB-T-C].[Trading Code].&["
)
,","
)
If Parameters!TradingName.Value is equal to a string of this format MEC,RSA then maybe join is not required:
StrToSet(
"{"
+
Replace(
"[Dim Branch].[HierarchyB-T-C].[Trading Code].&["
+
Parameters!TradingName.Value
, ","
,"],[Dim Branch].[HierarchyB-T-C].[Trading Code].&["
)
+
"]}"
,constrained)
To pass multiple value from parameter, i just followed the steps
1 Add parameters and name it like
Under dataset properties (shared dataset properties as well) , the Parameters tab write an expression like this way
=Split(Parameters!TradingName.Value,",")
in Shared dataset, write the MDX with WHERE (StrToSet(#TradingName))
SELECT
{[Total]} ON COLUMNS
,
{
[Dim Account].[Account Type].&[Income]
}
*
STRTOMEMBER("[Dim Fiscal Year].[HierarchyFiscal].[E Month].&[" + #FiscalYear +"]&[" + FORMAT(Now(),"MMMM") +"].PREVMEMBER")
*
ORDER
(
{
[Dim Branch].[Branch Name].[Branch Name]
},[Total], BDESC
)
ON ROWS
from [CubeProfitLoss]
WHERE (StrToSet(#TradingName))
when you want to preview the multiple value, make sure you are using , to separate trading name likewise

Parameterized MDX query in SSRS 2008 with Multiple Rank Columns

I'm struggling to figure this one out and was hoping someone out there might be able to help.
I have an SSRS (2008) report that connects directly to an SSAS OLAP Cube. I have 5 different columns, each showing a different measure, broken out by the "Manager" dimension. I also have parametrized dropdowns in SSRS that filter the data based on various things.
Here's the code that got me to this point:
SELECT
NON EMPTY{
[Measures].[Metric A]
,[Measures].[Metric B]
,[Measures].[TMetric C]
,[Measures].[Metric D]
,[Measures].[Metric E]
} ON COLUMNS
,NON EMPTY{
([Ops Hierarchy].[Manager].[Manager].ALLMEMBERS )
} DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM
(
SELECT
(
STRTOSET(#CompleteDateCalendar, CONSTRAINED) ) ON COLUMNS
FROM
(
SELECT
(
STRTOSET(#City, CONSTRAINED) ) ON COLUMNS
FROM
(
SELECT
(
STRTOSET(#Region, CONSTRAINED) ) ON COLUMNS
FROM
(
SELECT
(
STRTOSET(#Country, CONSTRAINED) ) ON COLUMNS
FROM
[CUBE]
)
)
)
)
WHERE
(
IIF( STRTOSET(#Country, CONSTRAINED).Count = 1, STRTOSET(#Country, CONSTRAINED)
, [Ops Hierarchy].[Division Name].currentmember )
, IIF( STRTOSET(#Region, CONSTRAINED).Count = 1, STRTOSET(#Region, CONSTRAINED)
, [Ops Hierarchy].[Region Name].currentmember )
, IIF( STRTOSET(#City, CONSTRAINED).Count = 1, STRTOSET(#City, CONSTRAINED)
, [Ops Hierarchy].[System Name].currentmember )
, IIF( STRTOSET(#CompleteDateCalendar, CONSTRAINED).Count = 1, STRTOSET(#CompleteDateCalendar, CONSTRAINED)
, [CompleteDate].[Calendar].currentmember )
)
CELL PROPERTIES VALUE, BACK_COLOR, FORE_COLOR, FORMATTED_VALUE, FORMAT_STRING, FONT_NAME, FONT_SIZE, FONT_FLAGS
And of course, SSRS automagically created the corresponding dropdowns for each #parameter.
Now, here's where I need help:
I have a new requirement to add a "Rank" column for each metric. So, for example, next to the "Metric A" column, there will be another column called "Metric A Rank" that ranks the manager on that row against the other managers that are showing on the report (based on the parameters selected in the dropdowns).
Now, I know that I can add:
WITH
SET [OrderedSet1] AS ORDER(FILTER([Ops Hierarchy].[Manager].MEMBERS,[Measures].[Metric A] <> NULL),[Measures].[Metric A],BASC)
MEMBER [Measures].[Metric A Rank] AS RANK([Ops Hierarchy].[Manager].CurrentMember,[OrderedSet1])
SET [OrderedSet2] AS ORDER(FILTER([Ops Hierarchy].[Manager].MEMBERS,[Measures].[Metric B] <> NULL),[Measures].[Metric B],BASC)
MEMBER [Measures].[Metric B Rank] AS RANK([Ops Hierarchy].[Manager].CurrentMember,[OrderedSet2])
etc, to the top of the MDX query, and then reference [Measures].[Metric A Rank] and [Measures].[Metric B Rank] in my select statement.
What I don't know how to do is filter the sets with the SSRS dropdowns so that I'm ranking against only what is showing on the report.
So for example, if someone has Country="USA", Region = "South", City = "Atlanta" and CompleteDate = "Jan 2012" selected in SSRS, and I rank Metric A against OrderedSet1, then I only want to show how each manager ranks against other managers in Atlanta for Jan 2012.
How do I "parameterize" the sets in the WITH clause using the SSRS dropdowns so that I'm only ranking against the subset that the user has selected?
Thanks in advance for your help!
in Set declaration you can use
SET [OrderedSet1] AS ORDER(FILTER([Ops Hierarchy].[Manager].MEMBERS*
[Ops Hierarchy].[System Name].currentmember
,[Measures].[Metric A] <> NULL),[Measures].[Metric A],BASC)

Passing MultiValue Parameter in MDX

How to pass MultiSelect parameter from SSRS to MDX?
I tried as below which is not working as expected:
WHERE ({IIF( STRTOSET(#Name, CONSTRAINED).Count = 1,
STRTOSET(#Name, CONSTRAINED), [Name].currentmember )})
You can use directly :
WHERE ( STRTOSET(#Name, CONSTRAINED) )
or (not sure about this ) :
WHERE ( IIF( STRTOSET(#Name, CONSTRAINED).Count = 1,
STRTOSET(#Name, CONSTRAINED),
STRTOMEMBER(#Name, CONSTRAINED) ) )
However SSAS and set slicers are not always good friends. If possible use MDX Subselects instead :
WHERE ( SELECT STRTOSET(#Name, CONSTRAINED) ON 0 FROM .. )