mdx topcount results not as expected - ssas

When I run the query below I only get 2 records back. If I drop the TOPCOUNT, I get 508 records.
Why is it not giving me the top 5 from the 508 records? What am I missing?
with
MEMBER Measures.[EmailCount] as IIF(ISEMPTY([Measures].[Tran Count]), 0 ,[Measures].[Tran Count])
MEMBER Measures.[IncomePerEmail] as
[Measures].[Amount]/ IIF(Measures.[EmailCount] = 0, 1 , Measures.[EmailCount] )
MEMBER Measures.[Income Range] as
CASE
WHEN Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] ) <= 10000 THEN '0-10000'
WHEN Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] ) <= 50000 THEN '10001-50000'
WHEN Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] ) <= 100000 THEN '50001-100000'
WHEN Sum(EXISTING [Dim IFA Details].[Parent Key].[Adviser Group].Members,
Measures.[Amount] ) <= 200000 THEN '100001-200000'
else '> 200000'
end
SELECT { [Measures].[Amount] , Measures.[EmailCount], measures.[Income Range], Measures.[IncomePerEmail] }
ON COLUMNS,
TOPCOUNT(
NONEMPTY([Dim IFA Details].[Parent Key].[Adviser Group].Members, Measures.Amount)
, 5
, Measures.[IncomePerEmail]
)
having Measures.[Income Range] = '10001-50000'
on rows
FROM [Income and Emails Cube]
where [Dim Date].[Fiscal Year].&[FY 13/14]

You have a HAVING clause which basically filters the set(of 5 records).
TOPCOUNTgets you 5 members but when the filtering happens, only two of the members meet the criteria Measures.[Income Range] = '10001-50000'
If you want to verify this, ORDER the query based on Measures.[IncomePerEmail] and see if the "top 5 records" have income ranges as '10001-50000'

Related

Convert sql rank to mdx rank

This is my sql code - I want to convert it into an mdx query.
Also those results set use into power bi report.
I am unable to write this sql query into mdx query. Can anybody help me?
Select * From(
Select
dense_RANK()over(partition by t.MonthName order by t.amount desc)rank
,t.*
From(
Select DSP.SalesPointShortName ,dd.MonthName
,SUM(fs.salesAmount)Amount
From FactSales FS
INNER JOIN DimDate dd on fs.DateKey=dd.DateKey
INNER JOIN DimSalesPoint DSP on DSP.SalesPointID=FS.SalesPointID
group by dsp.SalesPointShortName ,dd.MonthName
)as t
)as f where f.rank=1
My expected output is:
Lots of google searching i have the answer from below link
After following this link desire results comes.
https://bipassion.wordpress.com/2013/06/22/mdx-dense-rank/
`
WITH SET [Sorted Models] AS
// For each month get Top 25 records, choosed a Top 25 from business case
Generate (
[Dim Date].[Month Name].[Month Name].Members,
TopCount
( nonempty(
{
[Dim Date].[Month Name].CurrentMember
* [Dim Sales Point].[SalesPoint].[Sales Point Short Name].MEMBERS
}
,[Measures].[Sales Amount]
)
, 1
,[Measures].[Sales Amount]
)
)
//Select
//[Measures].[Sales Amount] on 0,[Sorted Models] on 1
//From [MdCubeTest]
//where [Dim Product Group Item].[Sub Category Name].&[Bag]
MEMBER [Measures].[Rank] AS
// Get the Rank of current member Tuple to Current Month Set
// Do not use Sorted Models set due to dynamic for each set
Rank (
(
[Dim Date].[Month Name].CurrentMember
, [Dim Sales Point].[SalesPoint].CurrentMember
)
, Generate ( [Dim Date].[Month Name].CurrentMember,
TopCount
( nonempty(
{ [Dim Date].[Month Name].CurrentMember
* [Dim Sales Point].[SalesPoint].[Sales Point Short Name]
}
,[Measures].[Sales Amount]
)
, 25
,[Measures].[Sales Amount]
)
)
, [Measures].[Sales Amount]
)
MEMBER [Measures].[Previous Set Index] AS
// Get the Set Index using Rank
(
[Measures].[Rank] - 2
)
MEMBER [Measures].[Dense Rank] AS
// Get the Dense Rank using the Index position value
CASE
WHEN [Measures].[Rank] = 1
THEN 1
ELSE
(
[Sorted Models].Item([Measures].[Previous Set Index]),
[Measures].[Dense Rank]
)
+
Iif
(
(
[Sorted Models].Item([Measures].[Previous Set Index]),
[Measures].[Sales Amount]
)
=
[Measures].[Sales Amount]
,0
,1
)
End
SELECT
{
[Measures].[Sales Amount]
, [Measures].[Rank]
, [Measures].[Dense Rank]
//, [Measures].[Previous Set Index]
} ON rows
,NON EMPTY
{
// FILTER Can be used to get the TOP 3 using DENSE RANK
FILTER (
[Sorted Models]
, [Measures].[Dense Rank] <=1
)
} ON columns
FROM [MdCubeTest]
where [Dim Product Group Item].[Sub Category Name].&[Bag]`

MDX query to pivot table based on condition

I'm trying to write MDX query for pivot table.
Similar query in RDBMS is like this:
SELECT stats_Date
,ISNULL(SUM(clicks), 0) AS clicks
,ISNULL(SUM(CASE WHEN ad_type IN (1,3) THEN clicks END), 0) AS keyword_clicks
,ISNULL(SUM(CASE WHEN ad_type IN (2,3) THEN clicks END), 0) AS direct_clicks
FROM STATS_TABLE (NOLOCK)
WHERE stats_Date BETWEEN '2015-06-01' AND '2015-06-30'
GROUP BY stats_Date
I've two dimensions [DIM TIME] & [DIM AD TYPE]
I've tried below MDX query for this:
WITH
MEMBER [Measures].[Clicks Keyword] AS
IIF
(
[DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
,[Measures].[clicks]
,0
)
SELECT {
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
,{
[DIM TIME].[CalendarHierarchy].[Date]*[DIM AD TYPE].[Ad Type].[Ad Type]
} ON ROWS
FROM [CM_STATS_CUBE]
WHERE ([DIM TIME].[Month].&[201506]:[DIM TIME].[Month].&[201506]})
Sample output of this MDX query looks like this:
Clicks Clicks Keyword
20150501 Invalid (null) 0
20150501 unknown 200 0
20150501 Keyword 500 0
20150501 Ads 300 300
20150502 Invalid (null) 0
20150502 unknown 400 0
20150502 Keyword 600 0
20150502 Ads 500 500
but I want to only group by stats_date and the expected output is:
Clicks Clicks Keyword
20150501 1000 300
20150502 1500 500
Similar example for testing in [Adventure Works] cube database:
WITH
MEMBER [Measures].[Internet Sales Amount US] AS
IIF( [Customer].[Customer Geography].CurrentMember IS [Customer].[Customer Geography].[Country].&[United States]
,[Measures].[Internet Sales Amount]
,NULL
)
SELECT {
[Measures].[Internet Sales Amount]
,[Measures].[Internet Sales Amount US]
} ON 0
,NON EMPTY{[Date].[Calendar].[Date]} ON 1
FROM [Adventure Works]
WHERE {[Date].[Date].&[20050701]:[Date].[Date].&[20050702]}
You don't need to bother with the cross-join [DIM TIME].[CalendarHierarchy].[Date]*[DIM AD TYPE].[Ad Type].[Ad Type]
WITH
MEMBER [Measures].[Clicks Keyword] AS
IIF
(
[DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
,[Measures].[clicks]
,0
)
SELECT
{
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
,{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
FROM [CM_STATS_CUBE]
WHERE
[DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
Also I would suggest using null rather than 0 in your IIF function - this should tidy up the result and speed things up:
WITH
MEMBER [Measures].[Clicks Keyword] AS
IIF
(
[DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
,[Measures].[clicks]
,null //<<<<<<<<<<<<<<<<< better to use null rather than 0
)
SELECT
{
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
, NON EMPTY //<<<<<<<<<<<<<<<<< now if Clicks and Clicks Keyword are both null the respective row will be excluded
{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
FROM [CM_STATS_CUBE]
WHERE
[DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
Edit
I'd not read your script in enough detail - apologies. You can just just aggregate a set of two tuples:
WITH
MEMBER [Measures].[Clicks Keyword] AS
Sum
(
{
([DIM AD TYPE].[Ad Type].&[1],[Measures].[clicks])
,([DIM AD TYPE].[Ad Type].&[3],[Measures].[clicks])
}
)
SELECT
{
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
, NON EMPTY //<<<<<<<<<<<<<<<<< now if Clicks and Clicks Keyword are both null the respective row will be excluded
{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
FROM [CM_STATS_CUBE]
WHERE
[DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
The AdvWrks example you posted would just be a single tuple:
WITH
MEMBER [Measures].[Internet Sales Amount US] AS
(
[Customer].[Customer Geography].[Country].&[United States]
,[Measures].[Internet Sales Amount]
)
SELECT {
[Measures].[Internet Sales Amount]
,[Measures].[Internet Sales Amount US]
} ON 0
,NON EMPTY{[Date].[Calendar].[Date]} ON 1
FROM [Adventure Works]
WHERE {[Date].[Date].&[20050701]:[Date].[Date].&[20050702]}
If you wanted to add in Canada then there seem to be three viable alternatives:
1.
WITH
MEMBER [Measures].[Internet Sales Amount US & Canada] AS
(
[Customer].[Customer Geography].[Country].&[United States]
,[Measures].[Internet Sales Amount]
)
+
(
[Customer].[Customer Geography].[Country].&[Canada]
,[Measures].[Internet Sales Amount]
)
2.
WITH
MEMBER [Measures].[Internet Sales Amount US & Canada] AS
Aggregate
(
{
[Customer].[Customer Geography].[Country].&[United States]
,[Customer].[Customer Geography].[Country].&[Canada]
}
,[Measures].[Internet Sales Amount]
)
3.
(Switch to Sum)
WITH
MEMBER [Measures].[Internet Sales Amount US & Canada] AS
Sum
(
{
(
[Customer].[Customer Geography].[Country].&[Canada]
,[Measures].[Internet Sales Amount]
)
,(
[Customer].[Customer Geography].[Country].&[United States]
,[Measures].[Internet Sales Amount]
)
}
)
Try this:
WITH
MEMBER [Measures].[Clicks Keyword] AS
AGGREGATE({[DIM AD TYPE].[Ad Type].&[1], [DIM AD TYPE].[Ad Type].&[3]}, [Measures].[Clicks])
SELECT NON EMPTY
{
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
, NON EMPTY
{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
FROM [CM_STATS_CUBE]
WHERE
([DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506]);

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.

Optimize a MDX Query

I am quite new to MDX and I need some help with this query.
Generate(
filter(
[Dim Products].[Product].[Product].members
*
[Dim Date].week.week.members,
[Measures].[Price]
),
nonempty(
topcount(
[Dim Price].[Price].[Price]
*
[Dim Products].[Product].currentmember
*
[Dim Date].week.currentmember,
1,
[Measures].[Price Count]
)
)
)
I am using the above Named Set in a dashboard tool (Dundas Dashboard) in order to retrieve the MODE (price value that repeats the most). It does show correct results however it is slow. It takes 2-3 seconds if there is a filter on a single week and takes about 6-7 seconds if there is no filter on week (shows data for all weeks). And this is in SSMS but the client tool takes even longer to get the result set, sometimes timing out.
After some tests it appears that the number of the rows in the fact table does not affect the performance, I've drastically decreased it but still the same. The performance increased, however, once I've decreased the number of members in 2 of the dimension tables - [Dim Price], [Dim Products]. Initially it was taking 20+ seconds to get result set but improved to 6-7 seconds once I've decreased the number of members as follows:
Table | Rows Before | Rows After
[Dim Price] | 2400 | 620
[Dim Products] | 1080 | 101
This makes me think there is a Cartesian Product between the 3 dimensions that is affecting the performance.
I need someone to advise how I can improve the query to increase the performance.
Try the EXISTING function before the NONEMPTY function like this:
Generate(
filter(
[Dim Products].[Product].[Product].members
*
[Dim Date].week.week.members,
[Measures].[Price] //<<<<<<<<<<SHOULD THIS NOT INCLUDE A CONDITION e.g. [Measures].[Price] > 0 ?
),
EXISTING nonempty(
topcount(
[Dim Price].[Price].[Price]
*
[Dim Products].[Product].currentmember
*
[Dim Date].week.currentmember,
1,
[Measures].[Price Count]
)
)
)
Attempt 2:
Generate(
filter(
NONEMPTY(
[Dim Products].[Product].[Product].members
*
[Dim Date].week.week.members,
[Measures].[Price]
)
),
EXISTING nonempty(
topcount(
[Dim Price].[Price].[Price]
*
[Dim Products].[Product].currentmember
*
[Dim Date].week.currentmember,
1,
[Measures].[Price Count]
)
)
)
Attempt 3:
GENERATE(
FILTER(
NONEMPTY(
[Dim Products].[Product].[Product].MEMBERS
*
[Dim Date].week.week.MEMBERS
),
[Measures].[Price] > 0
),
TOPCOUNT(
NONEMPTY(
EXISTING
[Dim Price].[Price].[Price]
*
[Dim Products].[Product].currentmember
*
[Dim Date].week.currentmember,
[Measures].[Price Count]
),
1,
[Measures].[Price Count]
)
)

MDX bucketizing the result set and assign frequency

I have a scenario where a result set has to be bucketed and assign a frequency.
For example, the following MDX query:
WITH MEMBER [MEASURES].[PERC_1] AS
AGGREGATE ( EXISTING [DIM CUSTOMER].[CUSTOMER ID].[ALL].CHILDREN,[MEASURES].[AMOUNT])
SELECT
[MEASURES].[PERC_1] ON 0,
[DIM CUSTOMER].[CUSTOMER ID].CHILDREN,[DIM CUSTOMER].[NAME].CHILDREN
FROM [ANALYSIS DW]
WHERE ([DIM CUSTOMER].[ADDRESS].[ALL])
should return this result:
Perc1
C1 10
C2 0
C3 20
C4 30
C5 40
C6 50
C7 50
C8 50
C9 90
C10 100
Now, I want this result set to be divided into buckets. If my bucket size is 3, the buckets should be
0-30
31-60
61-100
These buckets are calculated based on the maximum and minimum values of the perc_1 measure above; i.e., 0 is minimum and 100 is maximum. Buckets are calculated as (0+100)/3 -- (0-30, 31-60, 61-100).
Now the results after the frequency distribution on the above result set should look as below -
frequency
0-30 4
31-60 4
61-100 2
I will not get the access to the OLTP design/SSAS Cube solution.
WITH SET [0-30 set] AS
Filter([DIM CUSTOMER].[CUSTOMER ID].CHILDREN,
[MEASURES].[PERC_1] >= 0 AND [MEASURES].[PERC_1] <= 30
)
SET [31-60 set] AS
Filter([DIM CUSTOMER].[CUSTOMER ID].CHILDREN,
[MEASURES].[PERC_1] >= 31 AND [MEASURES].[PERC_1] <= 60
)
SET [61-100 set] AS
Filter([DIM CUSTOMER].[CUSTOMER ID].CHILDREN,
[MEASURES].[PERC_1] >= 61 AND [MEASURES].[PERC_1] <= 100
)
MEMBER [DIM CUSTOMER].[CUSTOMER ID].[0-30] AS
NULL
MEMBER [DIM CUSTOMER].[CUSTOMER ID].[31-60] AS
NULL
MEMBER [DIM CUSTOMER].[CUSTOMER ID].[61-100] AS
NULL
MEMBER [Measures].[frequency] AS
CASE [DIM CUSTOMER].[CUSTOMER ID].CurrentMember
WHEN [DIM CUSTOMER].[CUSTOMER ID].[0-30] THEN
[0-30 set].Count
WHEN [DIM CUSTOMER].[CUSTOMER ID].[31-60] THEN
[31-60 set].Count
WHEN [DIM CUSTOMER].[CUSTOMER ID].[61-100] THEN
[61-100 set].Count
END
SELECT { [Measures].[frequency] } ON 0,
{
[DIM CUSTOMER].[CUSTOMER ID].[0-30],
[DIM CUSTOMER].[CUSTOMER ID].[31-60],
[DIM CUSTOMER].[CUSTOMER ID].[61-100]
} ON 1
FROM [ANALYSIS DW]
WHERE ([DIM CUSTOMER].[ADDRESS].[ALL])
I do not think you can do this completely within MDX in a way that the "3" is a parameter to the MDX query, as you need at least to have something like the member definitions for the buckets explicitly in the MDX statement. The WITH clause (or a session level CREATE statement) is the only place where you can create the members shown on the row axis, even if they are just used as placeholders and do not contain any logic.
You would need an external tool to generate a parameter specific MDX statement like that above.