Add multiple calculating filters in MDX - filter

I am really new to MDX but I have spent the past two days looking for an answer but failed. So I greatly appreciate your help and patience.
I am trying to query a Cube with filters on multiple dimensions, and I realize that there are many similar questions already there, like this or this.
The thing is, instead of specifying a particular content I am looking for, I am trying to set up filters that picks up all records that begins with a specific string. This requires left function in the filters (i.e. calculating filters?) but I cannot blend them nicely into the code.
My failed code is like this (the two filters should be in ANDrelation)
Select Non Empty ([Measures].[Sales]) ON 0
FROM [Cube_Name]
WHERE
(
FILTER
(
[Customer].[CustomerID].Members, Left([Customer].[CustomerID].CurrentMember.Name,4)="ABCD"),
[Product].[ProductID].Members, Left([Product].[ProductID].CurrentMember.Name,3)="EFG")
)
)
(My trial is based on the last answer here.)
I also read that there are some workarounds like CROSSJOIN WITH AGGREGATE or Sub-SELECT, but I just do not have any clue on 1)how to incorporate the conditions inside; 2) performance (I heard that CROSSJOIN can be slow).
I am not sure if I should mention it here, but I am actually implementing the MDX from Excel VBA by using the ADOMB.Cellset object. It only gives me the Grand total of the query I implemented under Cellset.Items(0) (there are no more items).
Thank you!

You need to split two sets into two filters:
Select
Non Empty [Measures].[Sales] on 0
From [Cube_Name]
Where
(
Filter(
[Customer].[CustomerID].[CustomerID].Members,
Left(
[Customer].[CustomerID].CurrentMember.Name,
4
) = "ABCD"
),
Filter(
[Product].[ProductID].[ProductID].Members,
Left(
[Product].[ProductID].CurrentMember.Name,
3
) = "EFG"
)
)

Related

Power Automate Flows - Filter Query not working as expected with multiple AND's

The filter query in this flow doesn't appear to be working as expected. I know for certain that the items it emails out afterwards have the first two toggles set to false. Is there something in the syntax that I'm missing? Or possibly in the date/time comparisons? This is my first dive into Power Automate, and its with someone elses flow. So any insight is greatly appreciated.
This is an example of what it looks like after running, and getting items where Confirmed = false.
Thank_x0020_You_x0020_Sent eq 'false' and Confirmed eq 'true' and EventDate lt '2021-07-20T00:00:00.0000000' and EventDate ge '2021-07-19'
Assuming EventDate is a DateTime data type, instead of the raw outputs try:
formatDateTime(outputs('<actionName>'), 'yyyy-MM-ddTHH:mm:ss')
It seems to me that having so many conditions for the query is not a good idea and less if dates are used.
It is better to do the query with one or two conditions and then filter the received data within an apply to each step
The first two conditions are Yes/No Columns, so they need to be 0 or 1 (not true/false) Silly mistake, don't know how I missed that.
I agree with both previous comments for cleaning up the query in general.

SSRS Matrix - Sorting rows by a specific column

Can somebody explain me how to properly sort "[Arrivals] group" by Count(SearchDate)] for particular "Departure" in this Matrix?
I tried this fx in Row Group Sorting Properities, but it didn't work.
[Count(SearchDate)]
Then I tried specify which column I would like to sort, but same problem.
=Count(IIF(Fields!Departures.Value = "PRG", 1, 0))
After deeper inspection I found that I am able to sort "[Arrivals] group" only by [Count(SearchDate)] but not grouped for particular "Departure".
After a advice in MSDN forum I tried this fx:
=IIF(Fields!Departures.Value = "PRG", Count(Fields!SearchDate.Value), 0)
In first view result looks good but only for the first couple of records.
When I tried pivot table in SQL server everything looks fine:
SELECT * FROM (SELECT Arrivals, Departures, SearchDate FROM Destination WHERE SearchDate > '2016-03-01T00:00:00' AND SearchDate < '2016-03-28T14:03:46') as a
PIVOT (COUNT(SearchDate) for Departures in (PRG, LON)) as PivotTable
Order by PRG Desc
I spent a lot of time and tried a lot of solution but I have realy no idea how to solve it.
Thank you very much for your help, Petr.
I faced the same problem before. Try using this expression:
=COUNT(
IIF(
Fields!Departures.Value="PRG",
COUNT(Fields!SearchDate.Value),
Nothing
)
)
It could be a pain since depending on the dataset number of rows it increases the report processing time causing poor performance, it works though.
Let me know if this helps.

MDX Query to find the last ever non empty value in icCube

Following the post from Chris Web I am looking for a fast way to find the last buy from a customer.
I use an MDX statement like the following:
WITH FUNCTION previous_buys() AS tail( nonempty({NULL:[Time].[Time].currentmember.prevmember} ,[measures].[sales amt]),1)
MEMBER [last buy] as previous_buys().(0).key
select [measures].[last buy] on 0
, [Customers].[Customers].[name].members on 1
from [Store Sales]
where [Time].[Time].[day].&[2015-12-20T00:00:00.000]
This gives as expected, but it is taking a very long time. Is there an easy way to speed this query up somehow. As icCube is somewhat different then the Microsoft MDX I can not just copy Chris Web's solution.
Any idea's?
The main problem we're going to have with this solution is the scalability as we're evaluating {NULL:[Time].[Time].currentmember.prevmember} count members.
I thought that using a Reverse with a Head function would not evaluate the whole set, but the current implementation of the Empty function 'materializes' the set. This means we're evaluating all members. Not yet a valid solution.
Another solution and more elegant is using a recursive function. This will should reduce drastically the number of members evaluated.
WITH
FUNCTION previous_buys(t_) AS IIF( (t_,[Measures].[Amount]) = NULL, previous_buys(t_.prevMember), t_ )
MEMBER [last buy] as previous_buys( [Time].[Calendar].current).name
SELECT
[measures].[last buy] on 0,
[Customers].[Geography].[Region] on 1
FROM [Sales]
WHERE [Time].[Calendar].[Year].[2006].[Q1 2006].[Jan 2006].[8 Jan 2006]
If you've a lot of empty dates you could complicate a bit the algorithm going down to a month level for checking emptiness. This will evaluate a whole month in one iteration instead of the 30/31 we'll have in the day version.
The last and fastest by an order of magnitude is relying of the aggregation engine of icCube. What we want here is a measure that returns the last existing day.
The idea would be to add a measure with a date as input value and max as aggregation method. Then we would use eval - important as we're caching the subcube - on the set with this new measure.
This is relatively quick using SSAS against AdvWrks. I amalgamated you two custom structures (& needed to change from FUNCTION as I don't think this is part of MS's implementation of mdx):
WITH
MEMBER [Measures].[previous_buys] AS
Tail
(
NonEmpty
(
{NULL : [Date].[Calendar].CurrentMember.PrevMember}
,[Measures].[Internet Sales Amount]
)
).Item(0).Item(0).Member_Key
SELECT
NON EMPTY
[Measures].[previous_buys] ON 0
,NON EMPTY
[Product].[Product Categories].[Product] ON 1
FROM [Adventure Works]
WHERE
[Date].[Calendar].[Date].&[20071015];
It results in the following:

Tabular DAX Daily Many To Many Association

I am almost at the end of my tether on a problem that i have in a model currently... basically, i have a 'temporal' many to many mapping table which maps commission rates for managers over time... these can change daily, (but do so rarely), so I've tried to avoid just having a huge table with the same values repeated albeit for different specific dates, if i do this anyway i end up with a 200 million record table, crucially though more than one manager can get commission for the sale of a certain product type :s
Note: Some commissions only go to a single manager, and some go to multiple, and this can switch over time..
What I've done instead is hold ValidFrom, and ValidTo dates in the mapping table...
Every solution i come up with is deathly slow, and i just have no idea if there even IS a solution at this point... here is a link to a very small sample:- http://1drv.ms/1gOr7uw
The area that i think is the most troublesome is actually getting the correct "rate" for a given Manager, on a given day... the only way i can seem to be able to do this is nested SUMX, but there must be something slicker that I'm missing?!
One thing i thought about (but failed to actually implement) was just to hold an effective date, and filter using that and leverage LASTNONBLANK() or something?
Perhaps someone with some fresh eyes can help me out? Pulling my hair out here!
Edit: Someone will probably say why don't i do this in the ETL, what i've not shown here is that I have other measures that don't need to be split by the managers, but instead the full amount should be reported for each... but the total not a sum of all the managers (aka, default M2M behaviour)
Perhaps I need two fact tables? Perhaps someone could model my data in Excel to achieve a 'split' of the Facts, as i see it, whichever way the problem is cut some calc is going to need to be done at run-time. I think?!
Ty.
Give this a try, I have not checked performance, but I don't expect them to be super... nevertheless, at least it looks elegant :)
Amount :=
SUMX (
SUMMARIZE (
Mapping,
Mapping[Manager],
Mapping[Rate],
Mapping[ValidFrom],
Mapping[ValidTo],
Products[Products],
"SalesInPeriod", Mapping[Rate]
* CALCULATE (
SUM ( Sales[Amount] ),
VALUES ( 'Date'[Date] ),
DATESBETWEEN (
'Date'[Date],
Mapping[ValidFrom],
Mapping[ValidTo]
)
)
),
[SalesInPeriod]
)
If you want to count, still keeping the temporal M2M working, this should do the trick:
Count :=
CALCULATE (
COUNTROWS ( Sales ),
GENERATE (
SUMMARIZE (
Mapping,
Mapping[ValidFrom],
Mapping[ValidTo],
Products[Products]
),
DATESBETWEEN (
'Date'[Date],
Mapping[ValidFrom],
Mapping[ValidTo]
)
),
VALUES ( 'Date'[Date] )
)
This latter version is easier, because it does not need the Rate and Manager (or, it needs the manager, but it is already in the filter context and no SUMX is required since you are aggregating using canonical M2M)

Subselecting with MDX

Greetings stack overflow community.
I've recently started building an OLAP cube in SSAS2008 and have gotten stuck. I would be grateful if someone could at least point me towards the right direction.
Situation: Two fact tables, same cube. FactCalls holds information about calls made by subscribers, FactTopups holds topup data. Both tables have numerous common dimensions one of them being the Subscriber dimension.
FactCalls FactTopups
SubscriberKey SubscriberKey
CallDuration DateKey
CallCost Topup Value
...
What I am trying to achieve is to be able to build FactCalls reports based on distinct subscribers that have topped up their accounts within the last 7 days.
What I am basically looking for an MDX equivalent to SQL's:
select *
from FactCalls
where SubscriberKey in
( select distinct SubscriberKey from FactTopups where ... );
I've tried creating a degenerate dimension for both tables containing SubscriberKey and doing:
Exist(
[Calls Degenerate].[Subscriber Key].Children,
[Topups Degenerate].[Subscriber Key].Children
)
Without success.
Kind regards,
Vince
You would probably find something like the following would perform better. The filter approach will be forced to iterate through each subscriber, while the NonEmpty() function can take advantage of optimizations in the storage engine.
select non empty{
[Measures].[Count],
[Measures].[Cost],
[Measures].[Topup Value]
} on columns,
{
NonEmtpy( [Subscriber].[Subscriber Key].Children,
( [Measures].[Topups Count],
[Topup Date].[Calendar].[Month Name].&[2010]&[3] ) )
} on rows
from [Calls] ;
You know how sometimes it's the simplest and most obvious solutions that somehow elude you? Well, this is apparently one of them. They say "MDX is not SQL" and I now know what they mean. I've been working at this from an entirely SQL point of view, completely overlooking the obvious use of the filter command.
with set [OnlyThoseWithTopupsInMarch2010] as
filter(
[Subscriber].[Subscriber Key].Children,
( [Measures].[Topups Count],
[Topup Date].[Calendar].[Month Name].&[2010]&[3] ) > 0
)
select non empty{
[Measures].[Count],
[Measures].[Cost],
[Measures].[Topup Value]
} on columns,
non empty{ [Test] } on rows
from [Calls] ;
Embarrassingly simple.

Resources