MDX sort order in Crossjoin - mdx

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.

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
)

How To Get All Items Created or Still Open For A Given Time

I am working with a system were items are created (postDate dimension) and closed (endDate dimension). The endDate column is always populated with the last time the item was seen. An item is considered closed in a certain time if its last seen date is before the date you are querying. Each row in the fact table has the item, postDate, endDate, locationID, and some other dimensions used for aggregations. What I am trying to accomplish is getting all items still active for a given time frame. For example I want to know all items posted in November 2008 or before November 2008 that has not yet closed. In SQL it would look something like:
SELECT C.geoCountyArea,TM.CalendarYear,COUNT(DISTINCT a.itemid)
FROM [dbo].[factTable] a
JOIN dbo.dimDate AS TM
ON TM.DateKey BETWEEN postDate AND endDate
JOIN [dbo].[dim_geography] C
ON A.geographyID=C.geographyID
WHERE C.geoCountyArea = '1204000057'
AND TM.CalendarYear = 2008 AND TM.MonthNumberOfYear = 11
GROUP BY C.geoCountyArea,TM.CalendarYear
ORDER BY C.geoCountyArea,TM.CalendarYear
This returns 27,715 which is expected. Now, in MDX this looks like:
WITH MEMBER Measures.[itemCount] AS
AGGREGATE(
{NULL:[PostDate].[Month Name].&[2008]&[11]} * {[EndDate].[Month Name].&[2008]&[11]:NULL},
[Measures].[Fact_itemCount]
)
SELECT NON EMPTY (
Measures.[itemCount]
) ON 0,
NON EMPTY (
{[PostDate].[Month Name].&[2008]&[11]},
{[Geography].[Geo County Area].&[1204000057]}
)ON 1
FROM [Cube];
This returns 27,717 - which is 2 more than the SQL version that could be due to items with no end Date posted. Now, the complication comes when I want to get more than one explicit time - for example item count for all months in 2008 or item count for all years. I looked up methods to link a given param to another one via roll playing dimensions and came across this link. I altered my script so it looks like:
WITH MEMBER Measures.[itemCount] AS
AGGREGATE(
{NULL:LINKMEMBER([DATE].[Calendar].CURRENTMEMBER
,[PostDate].[Calendar])}
* {LINKMEMBER([DATE].[Calendar].CURRENTMEMBER
, [EndDate].[Calendar]):NULL}
, [Measures].[Fact_itemCount]
)
SELECT {Measures.[jobCount]} ON 0,
NON EMPTY (
{[DATE].[Month Name].&[2008]&[11]},
{[Geography].[Geo County Area].&[1204000057]}
)ON 1
FROM [Cube];
This, however, returns only the items created in November 2008 - value of 14,884. If I add in other months I do get individual counts for each month but, again, these are just the items created in those months.
How do I get the "active" item count for a given month/year/quarter without having do explicitly declare the time values in the AGGREGATE?
Can you use NonEmpty?
WITH MEMBER Measures.[itemCount] AS
AGGREGATE(
{NULL:
NONEMPTY(
[PostDate].[Month Name].MEMBERS //<<AMEND TO EXACT STRUCTURE USED IN YOUR CUBE
,[DATE].[Calendar].CURRENTMEMBER
).ITEM(0).ITEM(0)}
* {NONEMPTY(
[EndDate].[Month Name].MEMBERS //<<AMEND TO EXACT STRUCTURE USED IN YOUR CUBE
,[DATE].[Calendar].CURRENTMEMBER
).ITEM(0).ITEM(0): NULL}
, [Measures].[Fact_itemCount]
)
...
This ended up being the solution that provided valid results (tested against SQL calls against the warehouse tables):
WITH MEMBER Measures.[itemCount] AS
AGGREGATE(
{NULL:LINKMEMBER([Post Date].[Calendar],
[Post Date].[Calendar])}
* {LINKMEMBER([Post Date].[Calendar],
[End Date].[Calendar]):NULL},
[Measures].[Fact_itemCount]
)
SELECT {Measures.[itemCount]} ON 0,
NON EMPTY (
{[Post Date].[Month Name].Children},
{[Geography].[Geo County Area].&[1204000057]}
)
FROM [Cube]
Not that I am doing LINKMEMBER against the post and end dates - not against the global Date measure.

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

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];

Dimension distinct count SSAS within the context of other dimensions

I have this MDX;
CREATE MEMBER CURRENTCUBE.[Measures].DistinctOrderCount<br/>
AS
DistinctCount([Order].[Order Id].[Order Id] - [Order].[Order Id].[1]),<br/>
FORMAT_STRING = "#,##0;-#,##0",
VISIBLE = 1, ASSOCIATED_MEASURE_GROUP = 'Fact Sales';
I am trying to do a distinct of orders (except Order Id=1) within the context of other dimensions in my fact table. For example, distinct order count by dim customers, dim city, dim state etc. but I am not able to achieve this. When I view my measure on a report, I get distinct count of order dimension which is 21 being displayed on all rows of customers.
This is the best way I solved this and I am happy with the results. Hope this may help others. The idea is, create a cube measure with aggregation type Distinct Count and set column binding on the column you want distinct count on. Then use the below MDX to filter out the dummy Order Id's from your distinct count.
create member currentcube.[Measures].OrderCount<br/>
as<br/>
distinctcount
(
existing
CROSSJOIN
(
Except([Orders].[Order Id].[Order Id], [Orders].[Order Id].&[1]),
[Measures].[Order Count]
)
),<br/>
FORMAT_STRING = "#,##0;-#,##0",
VISIBLE = 1, ASSOCIATED_MEASURE_GROUP='Order Count';

How to get max value using MDX Query

I'm trying to get maximum value for Dimension table where the data as referred with Fact table
WITH
MEMBER [Measures].[Max key] AS
Max
(
[DimAnchorDate].[Date Key].MEMBERS
,[DimAnchorDate].[Date Key].CurrentMember.Member_Key
)
SELECT
{
[Measures].[Max key]
} ON COLUMNS
FROM X;
This query is giving me output : 20141231
In FactTable we have data upto 20141031. From the above query I would like to get 20141031
So now I am trying to get max value from DimAnchordate table as same as it is coming in FactPatientDr Table (i.e 20141031).So please suggest me the best way to achieve this...
I think at the moment you are looking at Dates that are empty in certain parts of the cube space - try forcing to nonempty by using a measure from the FactPatientDr
WITH
MEMBER [Measures].[Max key] AS
Max
(
nonempty(
[DimAnchorDate].[Date Key].MEMBERS
,[Measures].[SomeMeasureInFactPatientDr]
)
,[DimAnchorDate].[Date Key].CurrentMember.Member_Key
)
SELECT
{
[Measures].[Max key]
} ON COLUMNS
FROM X;
I think we can use Tail function to get desired result with measure value as well:
select non empty([Measures].[Entered Case],
tail
(Order
([Calendar].[Date].[Date].members
,[Measures].[Entered Case]
,basc
)
,1
)) on 0 from [SolutionPartner]