MDX Query Tuple representation using ampersand - mdx

What is the difference between representing tuple in an mdx query as
[CF Type].[CF TYPE].&[6]
OR
[ValScen].[Scenario Type].&[Term Point Rates]
Can I use the &[number] and the &[actual string] format interchangeably? If the cube is generated by another system, can the &[6] be different for each generation in usual practice? Or is it safer to use StrToMember or StrToSet. But this is not efficient as per this article. To give some context, in my case I use it like in below pseudocode
SELECT NON EMPTY { [Measures].x} ON COLUMNS, NON EMPTY { (My Column1 * My Column2)} DIMENSION PROPERTIES MEMBER_CAPTION ON ROWS FROM ( SELECT ( { [CF Type].[CF TYPE].&[6] } ) ON COLUMNS FROM
( SELECT ( { [ValScen].[Scenario Type].&[Term Point Rates] } ) ON COLUMNS FROM [My Cube]]))
WHERE ( [ValScen].[Scenario Type].&[Term Point Rates], [CF Type].[CF TYPE].&[6] )

Those are members and not tuples. A Tuple would be surrounded by braces ().
I think they are interchangeable syntax if you’re using the caption such as .&[hello] and .[hello] but if you use the key then the ampersand is mandatory.

Related

MDX linkmember equivalent in DAX

Is there any equivalent of linkmemeber from MDX to DAX?
I am trying to migrate the following script from MDX to DAX
with
member TauxdetransformationQuartileRegion as ([Measures].[Taux_de_transformation_Region],[Bon Envoi].[Bon Envoi].&[True])
member Annees as [Date Creation].[Année].currentmember.name
select {
[Measures].[Tx_Real_Meilleur_Region]
,TauxdetransformationQuartileRegion
} on 0
FROM ( select strtoset(#Region) on 0 from test)
WHERE (
linkmember(strtotuple(#DateFin),[Mois Publication].[Mois de publication])
,{strtotuple(#DateDebut):strtotuple(#DateFin)}
,[Perimetre Ebusiness].[Périmètre E-Business].&[O]
,{[MER_Publication].[Detail Type Visiteur].&[Prospect],[MER_Publication].[Detail Type Visiteur].&[Client direct]}
,( - { [Origine_Marketing].[Entree Parcours].&[SiteAgent] } )
)
MDX query parameters are typically strings with member unique names ("[Dim].[Attr].&[Key]") which you must convert to a member with StrToMember(#Param). And if you need to switch hierarchies you the use LinkMember.
DAX parameters are just the values. So the parameter will work against any dimension. Thus LinkMember isn’t needed.
Here is an article about DAX parameters. For Date type parameters I forget if you just say 'Date'[Date] = #DateParam or if you have to say 'Date'[Date] = DATEVALUE(#DateParam). My recollection is that it depends on whether the parameter is Date type (use the first approach) or String type (use the DATEVALUE approach).

The expression specified in the EVALUATE statement is not a valid table expression

I'm working on a Tabular cube in Visual Studio.
I have a DAX formula in the cube that works fine:
SUMX(FILTER(factFHA, factFHA[EventCd]="D"), [LoanCount])
When I run it in SSMS as:
evaluate(
SUMX(FILTER(factFHA, factFHA[EventCd]="D"), [LoanCount])
)
it fails with following error:
Query (1, 1) The expression specified in the EVALUATE statement is not a valid table expression.
I have 2 other formulas that both work fine:
evaluate(factFHA)
evaluate(filter('factFHA', [EventCd] = "D"))
I can't figure out what is wrong with the SUMX with FILTER
Please advise. Thank you.
EVALUATE function only works if you pass a table or an expression that returns a table, you are passing a SUMX function which return a scalar value (Decimal).
The syntax to write queries using DAX, is as follows:
[DEFINE { MEASURE <tableName>[<name>] = <expression> } -> Define a session (optional) measure
EVALUATE <table> --> Generate a table using your measures or creating calculated columns
[ORDER BY {<expression> [{ASC | DESC}]}[, …] --> Order the returned table by a passed column or expression
[START AT {<value>|<parameter>} [, …]]] --> This is an ORDER BY Sub-clause to define from which the query results will start.
Define your measure then use then use it inside the EVALUATE clause using a expression that evaluates to a table.
DEFINE
MEASURE factFHA[MyMeasure] =
SUMX ( FILTER ( factFHA, factFHA[EventCd] = "D" ), [LoanCount] )
EVALUATE
( SUMMARIZE ( FILTER ( factFHA, factFHA[EventCd] = "D" ), factFHA[AnyColumnToGroup]
, "Sum of MyMeasure", SUM ( factFHA[MyMeasure] ) ) )
Let me know if this helps.

How to use operator "in" with MDX in SSRS?

I'm building an ssrs report with this MDX query:
SELECT
NON EMPTY { ([KeyWords Dim].[Keywords].[Keyword].ALLMEMBERS *
[Ad Dim].[Countries].[Countries].ALLMEMBERS *
[Creative Dim].[Creatives].[Title].ALLMEMBERS ) } ON ROWS,
[Measures].[Clicks] ON COLUMNS
FROM [CubeName]
WHERE ([Time Dim].[Day ID].&[20140701]:[Time Dim].[Day ID].&[20140701])
I want to add another where clause to get only result for specific countries, something like that:
Where [Getways Dim].[Countries].[Countries].ALLMEMBERS IN ([Getways Dim].[Country].[Countries].&["Germany"],[Getways Dim].[Country].[Countries].&["US"]...)
How to do the "IN" part?
Thanks
In MDX, you do not use IN, you specify a set. The easiest way to specify a set is to just a list of members on braces like this:
WHERE {
[Getways Dim].[Country].[Countries].&["Germany"],
[Getways Dim].[Country].[Countries].&["US"]
}
and to combine conditions on two different hierarchies like Time and country, you build a cross product like this (* is the cross product operator in MDX):
WHERE ([Time Dim].[Day ID].&[20140701]:[Time Dim].[Day ID].&[20140701])
*
{
[Getways Dim].[Country].[Countries].&["Germany"],
[Getways Dim].[Country].[Countries].&["US"]
}

SQL to MDX conversion

I have this where clause in sql language:
where (cond1=1 or cond2=1) and cond3=1
How can I get this result in MDX with the slicing(condition into the where)?
{[cond1].&[1],[cond2].&[1]} /*and*/ {[cond3].&[1]}
Thanks
Try to use a subcube:
Select
-- YOUR SELECTED MEASURES AND DIMENSIONS
From
(
Select
{[cond1].&[1],[cond2].&[1]} on 0
,{[cond3].&[1]} on 1
-- ,{more slices} on x
From [CubeName]
)
Hope this help!
You can use subcube expression as stated above, but this is not the only option. If you use subcube, you would increase query performance greatly (assuming the fact you don't perform crossjoins in it).
You can also use general WHERE keyword after last expression that returns cube:
select
{ .. } on 0,
{ .. } on 1
from (select { [Dim1].[X].allmembers } on 0)
where ([Dim2].[Y].&[Y1])
Or:
select
{ .. } on 0,
{ .. } on 1
from (select { [Dim1].[X].allmembers } on 0)
where {[DimTime].[Time].[Year].&[2001] : [DimTime].[Time].[Year].&[2015]}
This is applied at the end of execution, which means performance may decrease. However, if you need to apply external filter to all axis, this is the option you need.
Another way to filter member values is using tuple expressions:
with member LastDateSale as ( (Tail(EXISTING [DimTime].[Time].[Dates].members,1), [Measures].[ActualSales]) )
This will take your DimTime axis, apply external filter, get the last element from it and calculate [ActualSales] for it, if possible.

Parameterizing Asymmetric Set in MDX?

I upgraded to SQL server 2008 R2 from 2005, and now this query is no longer working(although I don't rule out something I did being the cause). I have simplified the names/query to demonstrate the issue:
SELECT
NON EMPTY
{
[BizDim].[County].[County]
* [BizDim].[name].[name]
}
ON COLUMNS,
{
[Biz Line Type Dimension].[Line Number].[Line Number]
* [Biz Line Type Dimension].[Display Name].[Display Name]
}
ON ROWS
FROM [TPS Data View]
Where (
STRTOSET("{[BizDim].[County ID].&[16]}", CONSTRAINED)
,STRTOSET("{([BizDim].[Corp].[Corp].ALLMEMBERS,[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].&[x]),([BizDim].[Corp].[Corp].&[x],[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].ALLMEMBERS)}")
)
Essentially this is a logical OR saying if column Corp == 'x' OR HQ == 'x' then include it in the result. This is known as an assymmetric(sic) set.
The above gives the error:
The Tuple function expects a tuple expression for the 3 argument. A tuple set expression was used.
I can remove the STRTOSET function and it works perfectly:
Where (
STRTOSET("{[BizDim].[County ID].&[16]}", CONSTRAINED)
,{([BizDim].[Corp].[Corp].ALLMEMBERS,[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].&[x]),([BizDim].[Corp].[Corp].&[x],[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].ALLMEMBERS)}
)
However, this is no good because the actual query is parameterized, so it must work with a STRTO* function:
Where (
STRTOSET(#Counties, CONSTRAINED)
,STRTOSET(#BizTypes)
)
I have tried STRTOTUPLE and get the same error.
I could build the query dynamically but I'd rather avoid taking that risk, especially given that it worked fine before with a parameter.
So the question is, how to get this assymmetric set to work as a parameter again in SQL Server 2008 R2 SSAS?
Update:
Note that this eliminates the error by replacing the keys will ALLMEMBERS, but doesn't actually filter anything so it is useful only to show in general my syntax doesn't seem to be bad:
Where (
STRTOSET("{[BizDim].[County ID].&[16]}", CONSTRAINED)
,{([BizDim].[Corp].[Corp].ALLMEMBERS,[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].ALLMEMBERS),([BizDim].[Corp].[Corp].ALLMEMBERS,[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].ALLMEMBERS)}
)
I did manage to get this working in a less dynamic way, but quite annoying. Basically my filter would need to be divided into many different parameters because I would need a STRTOSET call for each one:
Where (
STRTOSET("{[BizDim].[County ID].&[16]}", CONSTRAINED)
,{
STRTOSET("([BizDim].[Corp].[Corp].ALLMEMBERS,[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].&[x])")
,STRTOSET"([BizDim].[Corp].[Corp].&[x],[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].ALLMEMBERS)")
}
)
[edited after comments]
Where
STRTOSET("{[BizDim].[County ID].&[16]}", CONSTRAINED)
* STRTOSET("{([BizDim].[Corp].[Corp].ALLMEMBERS,[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].&[x]),([BizDim].[Corp].[Corp].&[x],[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].ALLMEMBERS)}")
They might be an ambiguity with the ( x, y, z ) notation which is either a tuple or a parenthesis operator; e.g., ( {}, {} ) is a crossjoin.
Perhaps you need an explicit wrapping into a set :
{ [BizDim].[HQ].[HQ].&[x] }
Or replace:
([BizDim].[Corp].[Corp].ALLMEMBERS,[BizDim].[Local].[Local].ALLMEMBERS,[BizDim].[HQ].[HQ].&[x])
with an explicit crossjoin:
{ [BizDim].[Corp].[Corp].ALLMEMBERS * [BizDim].[Local].[Local].ALLMEMBERS * { [BizDim].[HQ].[HQ].&[x] } }
Hope that helps.