Simple MDX Filter Query - ssas

Can anyone explain why this one fails :
WITH MEMBER [Measures].[T]
as
Filter(
[Customer].[Customer Name].Children,
[Measures].[Sales] > 65042.79
)
SELECT
[Measures].[T] on 0
FROM [SalesCube]
while this one is fine?
SELECT
Filter(
[Customer].[Customer Name].Children,
[Measures].[Sales] > 65042.79
) on 0
FROM [SalesCube]
The first one gives an errror
"The function expects a string or numeric expression for the argument. A tuplet set expression was used."
They look exactly the same to me.

Realised that it should have been
WITH SET [T]
as
Filter(
[Customer].[Customer Name].Children,
[Measures].[Sales] > 65042.79
)
SELECT
[Measures].[T] on 0
FROM [SalesCube]

Related

MDX SSAS Rank rownumber function

I have an existing SSRS report out of T-SQL query and I am trying to recreate it using MDX queries on SSAS cube. I am stuck with rewriting Row num and rank logic to MDX.
It is written as:
SELECT ceil((ROW_NUMBER() OVER (PARTITION BY PRODUCT ORDER BY YEARMONTH))/12)
Rank1 in the SQL. Can someone tell me if this can be done using MDX? In the cube, PRODUCT and YEARMONTH are coming from separate dimensions.
Thank you for your help!
There is the Rank() function. For example:
with
Dynamic Set OrderedSet as
Order(
NonEmptyCrossJoin(
[Date].[Year].[Year].Members,
[Product].[Product].[Product].Members,
[Measures].[Invoice Count],
2
),
[Measures].[Invoice Count],
BDESC
)
Member [Measures].[Rank] as
Rank(
([Client].[Client].Currentmember,[Date].[Year].CurrentMember),
OrderedSet
)
select {[Measures].[Invoice Count],[Measures].[Rank]} on 0,
non empty OrderedSet on 1
from [BI Fake]
where ([Date].[Day].&[20160120])
You can read in details about it from my blog post.
You can use Generate to repeat ranks like this:
WITH
SET [SalesRank] AS
Generate
(
[Customer].[Customer Geography].[State-Province]
,Order
(
NonEmpty
(
(
[Customer].[Customer Geography].CurrentMember
,[Product].[Product Categories].[Subcategory]
)
,{[Measures].[Internet Sales Amount]}
)
,[Measures].[Internet Sales Amount]
,BDESC
)
)
MEMBER [Measures].[CategoryRank] AS
Rank
(
(
[Customer].[Customer Geography].CurrentMember
,[Product].[Product Categories].CurrentMember
)
,Exists
(
[SalesRank]
,[Product].[Product Categories].CurrentMember
)
)
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[CategoryRank]
} ON 0
,[SalesRank] ON 1
FROM [Adventure Works];
It results in this:

Create Set to get Last month of Each Year

I would like to create a set that returned the last Date for each year. For example all previous years would return December, but the current year would only return the current month.
WITH
SET testset AS
NonEmpty
(
Generate
(
{
OpeningPeriod([Date].[Calendar].[Month])
:
ClosingPeriod([Date].[Calendar].Month)
}
,{[Date].[calendar].CurrentMember}
)
,[Measures].[Sale Amount]
)
SELECT
NON EMPTY
(
[Measures].[Sale Amount]
,[Date].[Year].[Year]
) ON 0
,NON EMPTY
[testset] ON 1
FROM [Cube]
Here is an example of a script that returns the values for each month. I've tried using tail and lastchild, but that only returns the most recent. I would like it to return for every Year.
In terms of just the last month - ignoring whether there is data for it or not the following:
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,1
)
)
SELECT
{} ON 0
,[LastMths] ON 1
FROM [Adventure Works];
Returns this:
If I want to adapt the above so that it is the last month per year that has data for a specific measure then wrap NonEmpty around the set created by Descendants:
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
NonEmpty //<<new
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,[Measures].[Internet Sales Amount] //<<new
)
,1
)
)
SELECT
{} ON 0
,[LastMths] ON 1
FROM [Adventure Works];
It now gives us this:
We can then add in the tuple you have on rows (I have used the attribute hierarchy this time for years as [Date].[Calendar] is already in use)
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
NonEmpty
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,[Measures].[Internet Sales Amount]
)
,1
)
)
SELECT
NON EMPTY
(
[Measures].[Internet Sales Amount]
,[Date].[Calendar Year].[Calendar Year]
) ON 0
,[LastMths] ON 1
FROM [Adventure Works];
Now we get this:
#Whytheq has already given a very good solution. Treat this as an alternative. This might be a tad faster as it doesn't use the GENERATE function (not sure though!).
Have a calculated/cube measure which basically tells whether a month is the last month of the year. Then select those months out of the set of months.
with member measures.islastchild as
iif
(
[Date].[Calendar].currentmember is
[Date].[Calendar].currentmember.parent.parent.parent.lastchild.lastchild.lastchild,
1,
null
)
The member measures.islastchild returns 1 if the month is the last month of the year. Else it would return null.
set lastmonths as
filter(
[Date].[Calendar].[Month].members,
measures.islastchild = 1
)
The set lastmonths is then the set you need.
edit
To further improve the performance, you can NonEmpty function instead of the iterative FILTER function.
set lastmonths as
NonEmpty(
[Date].[Calendar].[Month].members,
measures.islastchild
)
select lastmonths on 1,
{} on 0
from [Adventure Works]
EDIT 2: To get the last non month with sales
with member measures.islastnonemptychild as
iif
(
[Date].[Calendar].currentmember is
TAIL(NonEmpty([Date].[Calendar].currentmember.parent.parent.parent.lastchild.lastchild.children, [Measures].[Sale Amount])).ITEM(0),
1,
null
)
set nonemptylastmonths as
NonEmpty(
[Date].[Calendar].[Month].members,
measures.islastnonemptychild
)

Checking Multiple condition in case statement using MDX query

How to write the below case statement in mdx.I moved the below mentioned columns in the fact table.
sum(case when IsSummary = 1 and IsAudited = 1 and FinalAuditFlag = 1 then 1
else 0 end) AuditsCompleted,--Count - Completed Audits
i tried the below MDX query.
WITH
MEMBER [Measures].[count]
AS
(
case ([Measures].currentmember )
when 0 then ([Measures].[Is Summary] )
else 1
end
)
Select
{[Measures].[count]} on 0,
[Dim_table1].[TableId].members on 1
from [Dsv]
What you have done is almost correct. Just change .currentmember to an actual measure in your cube. Currently when you have the following it is referring to itself i.e. currentmember by the black arrow it referring to the measure count by the black arrow...
This is in AdvWrks:
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,{[Product].[Product Categories].[Category]} ON 1
FROM [Adventure Works];
It returns this:
If I want to replace the empty cell for Components the we can use CASE:
WITH
MEMBER [Measures].[count] AS
CASE [Measures].[Internet Sales Amount]
WHEN 0 THEN "XXX"
ELSE [Measures].[Internet Sales Amount]
END ,format_string = "#,###,##0"
SELECT
{
[Measures].[count]
} ON 0
,{[Product].[Product Categories].[Category]} ON 1
FROM [Adventure Works];
This now returns this:
IIF is used a lot more in MDX than CASE - IIF is nearly always faster. So the above equivalent using IIF is the following:
WITH
MEMBER [Measures].[count] AS
IIF
(
[Measures].[Internet Sales Amount] = 0
,"XXX"
,[Measures].[Internet Sales Amount]
)
,format_string = "#,###,##0"
SELECT
{[Measures].[count]} ON 0
,{[Product].[Product Categories].[Category]} ON 1
FROM [Adventure Works];
I am assuming that your requirement is to find the sum over all the members of [Dim Table1].[TableID] hierarchy.
If so, then the below should work for you:-
WITH MEMBER Measures.[Count] AS
SUM(
[Dim_table1].[TableId].CHILDREN,
[Measures].[Is Summary] * [Measures].[Is Audited] * [Measures].[Final Audited Flag] //If any is 0, it's 0, else 1
)
SELECT Measures.[Count]
FROM [Dsv]
Let me know if further slicers are needed to be added or if my understanding is incorrect.

Limiting date range using Filter

Without using the colon operator how do I filter the set AllDates to just 05Jan2005 to 10Jan2006?
WITH
SET [AllDates] AS
[Date].[Date].[Date].MEMBERS
MEMBER [Measures].[DTkey] AS
[Date].[Date].CurrentMember.Member_Key
MEMBER [Measures].[DTmemValue] AS
[Date].[Date].CurrentMember.MemberValue
MEMBER [Measures].[DTvalue] AS
[Date].[Date].CurrentMember.Value
SELECT
{[Measures].[DTmemValue]} ON 0
,Filter
(
[AllDates]
,
[Measures].[DTmemValue] > 0
) ON 1
FROM [Adventure Works];
I don't have Adv Wks but tested the below on mine and it worked well.
Is this what you're looking for?
WITH
SET [AllDates] AS
[Date].[date].[date].members
MEMBER [Measures].[DTkey] AS
[Date].[date].CurrentMember.Member_Key
MEMBER [Measures].[DTmemValue] AS
[Date].[date].CurrentMember.MemberValue
MEMBER [Measures].[DTvalue] AS
[Date].[date].CurrentMember.Value
SELECT
{[Measures].[DTmemValue]} ON 0
,Filter
(
[AllDates]
,
CDate([Measures].[DTmemValue]) >= CDate("01/05/2005")
and CDate([Measures].[DTmemValue]) <= CDate("01/10/2006")
) ON 1
FROM [Adventure Works];
WITH
SET [AllDates] AS
[Date].[Date].[Date].MEMBERS
MEMBER [Measures].[DTkey] AS
[Date].[Date].CurrentMember.Member_Key
MEMBER [Measures].[DTmemValue] AS
[Date].[Date].CurrentMember.MemberValue
MEMBER [Measures].[DTvalue] AS
[Date].[Date].CurrentMember.Value
SELECT
{[Measures].[DTmemValue]} ON 0
,Filter
(
[AllDates]
,
CDate([Measures].[DTmemValue]) > CDate("2006-01-01")
) ON 1
FROM [Adventure Works];
More details about MDX Filtering can be found: http://chrish.com.au/blog/filtering-in-mdx/

MDX calculated member filtration uses measure

I need help with calculated member
I have this code
CREATE MEMBER CURRENTCUBE.[Measures].[Summary distribution by CSKU]
AS count(
NONEMPTY(
crossjoin(
descendants ([05_Goods].[CSKU].currentmember,,LEAVES),
descendants ([04_Agents].[Agents hierarhy],,LEAVES)
)
)
),
FORMAT_STRING = "###,##0;-###,##0",
NON_EMPTY_BEHAVIOR = { [Quantity] },
VISIBLE = 1 , DISPLAY_FOLDER = 'Distribution' , ASSOCIATED_MEASURE_GROUP = '01_Sales' ;
but I want to see a result without elements where sum([Measures].[Sales amount]) <> 0
How can I do it?
Thanks!
Dmitry
I don't see other choice than using the MDX Filter function :
...
AS count(
FILTER(
crossjoin(
descendants ([05_Goods].[CSKU].currentmember,,LEAVES),
descendants ([04_Agents].[Agents hierarhy],,LEAVES)
)
, [Measures].[Sales amount] <> 0)
)
You might try adding the NonEmpty to the descendants method to improve performance (if some descendants have no [Sales Amount].