MDX query to order (and topfilter) results after/with a crossjoin - ssas

I would like to order a set of results in an MDX query which also includes a crossjoin.
I have the following measures and dimensions:
[Measures].[Starts]
[Framework].[Framework Name]
[Framework].[Pathway Name]
I would like to create a list of the (corresponding) Framework and Pathway names that correspond to the top 25 numbers of [Measures].[Starts].
I have managed to output a FULL list of results using:
select [Measures].[Starts] on COLUMNS,
NON EMPTY CrossJoin(
Hierarchize({DrilldownLevel({[Framework].[Pathway Name].Children})}),
Hierarchize({DrilldownLevel({[Framework].[Framework Name].Children})})
) on ROWS
from [DataCube]
to create the following example output:
However, I need it to be sorted by the starts in descending order (and preferably only keep the top 25 results). I have tried almost everything and have failed. A google search didn't find any results.

Did you stumble across the TopCount function?
select [Measures].[Starts] on COLUMNS,
NON EMPTY
TopCount
(
CrossJoin
(
Hierarchize({DrilldownLevel({[Framework].[Pathway Name].Children})}),
Hierarchize({DrilldownLevel({[Framework].[Framework Name].Children})})
),
25,
[Measures].[Starts]
) on ROWS
from [DataCube]
Here's the msdn link.
H2H

For efficiency it is better to order the set before using the TopCount function:
WITH
SET [SetOrdered] AS
ORDER(
{DrilldownLevel([Framework].[Pathway Name].Children)}
*{DrilldownLevel([Framework].[Framework Name].Children)}
,[Measures].[Starts]
,BDESC
)
SET [Set25] AS
TOPCOUNT(
[SetOrdered]
,25
)
SELECT
[Measures].[Starts] on 0,
NON EMPTY
[Set25] on 1
FROM [DataCube];

Related

Sort measures where row and column axis are cross-joined in MDX

I've a table where there's two dimensions in the row axis crossjoined and two dimensions plus a measure crossjoined in the column axis. Eg:
I would like to sort the rows of a specific column, taking the image as an example I would like to sort all rows so the ones under France -> apples -> avg_sales are sorted. Eg:
I've been able to find many examples on how to do this when there's just a bunch of measures as columns (with no crossjoin) and many different dimensions crossjoined in the row axis but I'm not able to find anywhere how to solve this particular situation.
I tried something like the following:
SELECT CrossJoin(
[Country].[Country].members,
CrossJoin(
[Product Category].[Product].members,
{[avg_sales]}
)
) on columns,
Order(
Filter(
CrossJoin(
[Date].[Year].Members,
[Date].[Month].Members
),
NOT IsEmpty(avg_sales)
),
CrossJoin(
[Country].[Country].[France],
CrossJoin(
[Product Category].[Product].[apples],
{[avg_sales]}
)
),
BDESC
) ON ROWS
FROM [Main Cube]
But MDX Order() function signature doesn't allow it, it complains by saying:
Mondrian Error: No function matches signature 'Order(<Set>, <Set>, <Symbol>)'
This MDX expression on the row axis would do the trick:
ORDER(
CrossJoin([Date].[Year].Members, [Date].[Month].Members),
([Measures].[avg_sales], [Product Category].[Product].[apples]),
BASC
)
If you wanted to sort the months by sales but still keep the years together, then you could do this:
ORDER(
CrossJoin([Date].[Year].Members, [Date].[Month].Members),
[Date].[Year].CurrentMember.ORDERKEY,
BASC,
([Measures].[avg_sales], [Product Category].[Product].[apples]),
BASC
)
You could even sort the rows by the average sales across the selected countries and fruits on the column axis.
There's a free trial version of Pentaho EE which includes an OLAP client (Pentaho Analyzer) on Mondrian that generates these types of MDX expressions. You can use their Data Source Wizard to load your data, build a few reports and study the MDX to see how the ORDER MDX function is used.
https://www.hitachivantara.com/en-us/products/data-management-analytics/lumada-dataops/data-integration-analytics/download-pentaho.html
By the doc https://mondrian.pentaho.com/documentation/mdx.php
there is only 2 functions:
<Set> Order(<Set>, <Value>, <Symbol>)
<Set> Order(<Set>, <Value>)
The Order function must be some like this
Order(
Filter(
CrossJoin(
[Date].[Year].Members,
[Date].[Month].Members
),
NOT IsEmpty(avg_sales)
) *
CrossJoin(
[Country].[Country].[France],
CrossJoin(
[Product Category].[Product].[apples],
{[avg_sales]}
)
),
BDESC
)

custom count measure runs forever MDX

So this question goes off the one here
I've been trying to do a similar count measure and I did the suggested solution but it's still running.... and it's been more than 30 minutes with no results, while without that it runs in under a minute. So am I missing something? Any guidance would help. Here is my query:
WITH
MEMBER [Measures].[IteractionCount] AS
NONEMPTY
(
FILTER
(
([DimInteraction].[InteractionId].[ALL].Children,
[Measures].[Impression Count]),
[DimInteraction].[Interaction State].&[Enabled]
)
).count
SELECT
(
{[Measures].[IteractionCount],
[Measures].[Impression Count]}
)
ON COLUMNS,
(
([DimCampaign].[CampaignId].[CampaignId].MEMBERS,
[DimCampaign].[Campaign Name].[Campaign Name].MEMBERS,
[DimCampaign].[Owner].[Owner].MEMBERS)
,[DimDate].[date].[date].MEMBERS
)
ON ROWS
FROM
(
SELECT
(
{[DimDate].[date].&[2020-05-06T00:00:00] : [DimDate].[date].&[2020-05-27T00:00:00]}
)
ON COLUMNS
FROM [Model]
)
WHERE
(
{[DimCampaign].[EndDate].&[2020-05-27T00:00:00]:NULL},
[DimCampaign].[Campaign State].&[Active],
{[DimInteraction].[End Date].&[2020-05-27T00:00:00]:NULL}//,
//[DimInteraction].[Interaction State].&[Enabled]
)
I don't know if FILTER is affecting it in any way but I tried it with and without and it still runs forever. I do need it specifically filtered to [DimInteraction].[Interaction State].&[Enabled]. I have also tried to instead filter to that option in the WHERE clause but no luck
Any suggestions to optimize this would be greatly appreciated! thanks!
UPDATE:
I end up using this query to load data into a python dataframe. Here is my code for that. I used this script for connecting and loading the data. I had to make some edits to it though to use windows authentication.
ssas_api._load_assemblies() #this uses Windows Authentication
conn = ssas_api.set_conn_string(server='server name',db_name='db name')
df = ssas_api.get_DAX(connection_string=conn, dax_string=query))
The dax_string parameter is what accepts the dax or mdx query to pull from the cube.
Please try this optimization:
WITH
MEMBER [Measures].[IteractionCount] AS
SUM
(
[DimInteraction].[InteractionId].[InteractionId].Members
* [DimInteraction].[Interaction State].&[Enabled],
IIF(
IsEmpty([Measures].[Impression Count]),
Null,
1
)
)
SELECT
(
{[Measures].[IteractionCount],
[Measures].[Impression Count]}
)
ON COLUMNS,
(
([DimCampaign].[CampaignId].[CampaignId].MEMBERS,
[DimCampaign].[Campaign Name].[Campaign Name].MEMBERS,
[DimCampaign].[Owner].[Owner].MEMBERS)
,[DimDate].[date].[date].MEMBERS
)
PROPERTIES MEMBER_CAPTION
ON ROWS
FROM
(
SELECT
(
{[DimDate].[date].&[2020-05-06T00:00:00] : [DimDate].[date].&[2020-05-27T00:00:00]}
)
ON COLUMNS
FROM [Model]
)
WHERE
(
{[DimCampaign].[EndDate].&[2020-05-27T00:00:00]:NULL},
[DimCampaign].[Campaign State].&[Active],
{[DimInteraction].[End Date].&[2020-05-27T00:00:00]:NULL}//,
//[DimInteraction].[Interaction State].&[Enabled]
)
CELL PROPERTIES VALUE
If that doesn’t perform well the please describe the number of rows returned by your query when you comment out IteractionCount (sic) from the columns axis. And please describe how many unique InteractionId values you have.

MDX sort order in Crossjoin

I want to show a list of callers we have missed calls from within a daterange. I want te result to be ordered by date. But I can't figure out how to do this.
My MDX statement:
With
Member [Measures].[Gemist] AS
sum(
except({[CM resultaat].[Resultaat].[CM resultaat].allmembers},
{[CM resultaat].[Resultaat].[CM resultaat].[answer],[CM resultaat].[Resultaat].[CM resultaat].[answer overflow]}),
[Measures].[SN Gesprekken]
)
Select
order([Measures].[Gemist],[Datum].[Datum].currentMember.value, ASC) on 0,
nonempty(crossjoin(Hierarchize([ServiceNummer ANI].[Ani]),[Datum].[Datum].[Dag]),[Measures].[Gemist]) on 1
FROM (SELECT {[datum].[datum].[dag].[2020-04-01]:[datum].[datum].[dag].[2020-04-28]} ON 0 FROM [Cube])
After some google searches I tried this to order the measure by date but also tried to order the crossjoin. Output stays te same, no order on date:
Anyone has a solution for this?
You need to order the vertical axis (i.e., the axis 1):
order(
nonempty(
crossjoin( [ServiceNummer ANI].[Ani], [Datum].[Datum].[Dag] )
),
[Datum].[Datum].currentMember.key,
BASC
) on 1
using the key (or name) of the current member of the [Datum] dimension.
Hope that helps.

Union in MDX query

In my time dimensions i have 2013,2014,2015.
How can i make a Union in this mdx so i get the results from this mdx for all thoose years and not only for 2014 like in the example..
select NON EMPTY {[Measures].[Absatz Plan], [Measures].[Umsatz Plan], [Measures].[Absatz Effektiv], [Measures].[Umsatz Effektiv]} ON COLUMNS,
NON EMPTY Crossjoin(Hierarchize({([Time].[2014], [Artikel].[All Artikels], [Markt].[All Markts])}), {[Version].[14], [Version].[16], [Version].[18]}) ON ROWS
from [Budget]
Just apply CrossJoin twice:
select NON EMPTY
{[Measures].[Absatz Plan], [Measures].[Umsatz Plan], [Measures].[Absatz Effektiv], [Measures].[Umsatz Effektiv]}
ON COLUMNS,
NON EMPTY
CrossJoin(
Crossjoin(
{[Time].[2013], [Time].[2014], [Time].[2015]},
{([Artikel].[All Artikels], [Markt].[All Markts])}
),
{[Version].[14], [Version].[16], [Version].[18]}
)
ON ROWS
from [Budget]
I removed the Hierarchize, as I think it is not necessary in this context. It would order its argument by the order defined for the hierarchy in the cube. If the order of the result seems wrong, you could re-add it.

Can I reformulate this MDX query to use sets instead of an "And"?

with member [Measures].[BoughtDispenser] as
Sum(Descendants([Customer].[Customer].CurrentMember, [Customer].[Customer]),
Iif(
(IsEmpty(([Item].[ItemNumber].&[011074], [Measures].[Sale Amount]))
And IsEmpty(([Item].[ItemNumber].&[011069], [Measures].[Sale Amount]))
)
Or IsEmpty([Measures].[Sale Amount]),
0 , 1
)
)
select
{[Measures].[Sale Amount]} on columns,
non empty filter([Customer].[Customer].children, [Measures].[BoughtDispenser])
* {[Item].[ItemNumber].members}
on rows
from [Sales]
where [EnteredDate].[Quarter].&[2010-01-01T00:00:00]
;
The object is to show all the items purchased by customers who also bought either of the two dispensers (011069 and 011074).
I based the calculated member on a query I found to do basket analysis. I feel like there should be a way to write it with the set {[Item].[ItemNumber].&[011074], [Item].[ItemNumber].&[011069]} instead of the two IsEmpty tests. Everything I've tried ended up having every Customer in the result.
My environment is SQL Server Analysis Services 2005.
Yes I can! It just required a slightly different approach to the calculated member:
with member [Measures].[BoughtDispenser] as
Sum(Descendants([Customer].[Customer].CurrentMember, [Customer].[Customer])
* {[Item].[ItemNumber].&[011069], [Item].[ItemNumber].&[011074]},
[Measures].[Quantity Shipped]
)
select
{[Measures].[Sale Amount]} on columns,
non empty filter([Customer].[Customer].children, [Measures].[BoughtDispenser])
* {[Item].[ItemNumber].members}
on rows
from [Sales]
where [EnteredDate].[Quarter].&[2010-01-01T00:00:00]
;