I am trying to create a calculated measure that finds the difference between two measures by using the following mdx query
WITH MEMBER [Measures].[Available]
AS ([Measures].[Capacity days] ,[Project].[Projects by Name].[All],[Project].[Projects by Code].[All])
- ([Measures].[Worked Days] ,EXCEPT([Project].[Projects by Name].[Project].MEMBERS,
[Project].[Projects by Name].[Project].&[1214]),[Version].[Version].[Combined],[Charge].[Charge].[All])
In case of second measure Worked Days I want to access it with respect to all projects except one ,so am using EXCEPT function which results in the following error
" The function expects a string or numeric expression for the argument. A tuple set expression was used"
Is there any other way to perform this operation?
The query is mixing tuples with sets. Perhaps you can check this gentle introduction of MDX for main concepts and notations.
The second tuple is using a set (the result of EXCEPT) as its second member which is not possible. You could use the aggregate function as following to compute the [Worked Days] over the members of this set instead :
AS ( [Measures].[Capacity days], ... )
- Aggregate(
Except (
[Project].[Projects by Name].[Project].MEMBERS,
[Project].[Projects by Name].[Project].&[1214]
),
( [Measures].[Worked Days], ... )
)
Related
I inherited some mdx code which uses calculated members and the sum function. I need to make a new member using SUM but and OR (union?) set. I have tried various syntaxes but they all error.
I have code as below:
-- uses this date filter
set [as_of_month] as {strtomember("[Date].[Year - Month].[Month].&[" + cstr(format(cdate("Jul 2019"),"yyyy-MM")) + "-01T00:00:00]")}
-- member 1
member [SIONLY_MTH] as sum([as_of_month] * [Incident Details].[Is SI].[Is SI], [Measures].[Environment Impact Count])
-- member 2
member [MajorNC_Month] as sum([as_of_month] *
[Impact].[Impact].&[3] *
[Non Compliance].[Non Compliance Type].&[Major non-compliance],
[Measures].[Non Compliance Count]) + 0
-- I need a new member which is an OR of the previous 2, ie, count of
-- SI_ONLYMONTH or [MajorNC_Month] filtered by [as_of_month]
member [LegalSI_EnvSI_Month] as SUM([as_of_month] * {[Incident Details].[Is SI].[Is SI] , [Non Compliance].[Non Compliance Type].&[Major non-compliance]}
, [Measures].[Environment Impact Count]) + 0
The set inside the last sum function doesnt work, it returns #Error.
Does anyone know how to use a unioned set as the argument to the SUM function in mdx?
Thanks
Your problem basicly deals with the concepts of dimensionality and hierarchility
Try this
sum(
{
([as_of_month] * [Incident Details].[Is SI].[Is SI][Impact].[Impact].defaultmember[Non Compliance].[Non Compliance Type].defaultmember),
([as_of_month] * [Incident Details].[Is SI].defaultmember*[Impact].[Impact].&[3]*[Non Compliance].[Non Compliance Type].&[Major non-compliance])
}
,
[Measures].[Environment Impact Count])
Edit: Includes explanation on how and why the above query works.
In your problem you have two sets that have diffrent hierarchies in them. So you have to balance them. Lets take a look at your first set
sum([as_of_month] * [Incident Details].[Is SI].[Is SI],
[Measures].[Environment Impact Count])
This doesnt explicitly include "[Impact].[Impact]" however before executing SSAS takes the liberty to include [Impact].[Impact].defaultmember in the query. Based on this fact I balanced both of your sets by expicitly including the default members of attribute hierarchies that were orignally not part of your Set.
Next I encapsulaed them in "()" to indicate that they are a tuple of a larger Set.Then both these tuples are encapsulated in "{}" like this "{(tuple1),(tuple2)}"
I have a bunch of calculated members that I need to create which are referenced off a single date.
Rather than repeating the MDX that gets the date member for which the measure will be based off, is there a way to create the date member at the start, and then reference it throughout so that I don't have to repeat the MDX multiple times? I was thinking something like the below however it returns a NULL:
WITH MEMBER [Date].[Retail].[Closing Date] AS
IIF (
[Date].[Retail].CurrentMember.Level.Name = 'Date',
[Date].[Retail].CurrentMember.PrevMember,
[Date].[Retail].CurrentMember
)
MEMBER [Measures].[Closing New] AS
(
[Date].[Retail].[Closing Date],
[Measures].[On Hand Quantity]
)
SELECT
[Date].[Retail].[Date].Members ON ROWS,
{
[Measures].[On Hand Quantity],
[Measures].[Closing New]
} ON COLUMNS
FROM
Retail
WHERE
[Date].[Retail Year].&[2017]
As above, I want to use the Closing Date member multiple times for various calculations.
To investigate why it is returning null try something like the following to see if it is as you expect:
WITH
MEMBER [Measures].[nm] AS
[Date].[Retail].CurrentMember.Level.Name
SELECT
{
[Measures].[On Hand Quantity],
[Measures].[nm]
} ON 0,
[Date].[Retail].[Date].Members ON 1
FROM Retail
WHERE [Date].[Retail Year].&[2017];
(I also switched the declaration order inside the SELECT clause as it is standard to declare columns, as it is axis 0, first followed by rows)
Why yes, there is!
the pattern I follow here is to create a set of one member then reference the first item of that set.
with set currentDate as
[Date].[Retail].[Date].&[20160725]
then reference it in the remainder of your query as
currentDate.item(0)
I understand how to use the MDX Aggregate() and Sum() functions, and the differences between them.
(One interesting one is that the Sum of a measure defined at a higher level in a hierarchy over that level's Children multiplies the measure by the number of children - whereas Aggregate "correctly" returns just the value defined at the higher level).
The documented syntax on MSDN is:
Aggregate(Set_Expression [ ,Numeric_Expression ])
I've always used it with both arguments. But what does Aggregate do when only the set_expression argument is provided? The documentation (again from MSDN) is pretty obscure:
If a numeric expression is not provided, this function aggregates each measure within the current query context by using the default aggregation operator that is specified for each measure.
I tried it in an MDX query like this:
WITH MEMBER WeekSummedTotal AS
Aggregate([Days].[WeeksAndDays].CurrentMember.Children)
SELECT
{Measures.ThingoCount,Measures.WeekTotal,Measures.WeekSummedTotal} ON 0,
[Days].[WeeksAndDays].[WeekName] ON 1
FROM DateGRoupingTest
What would this do? Would Aggregate aggregate the cube's default measure over the set? Or the set Measures.Members? Or the set of other measures specified on the 0 axis?
None of these! The query runs and returns results, but the calcd measure WeekSumTotal shows #Error, with a completely nonsensical error:
Aggregate functions cannot be used on calculated members in the measures dimension
Now this is true, but completely irrelevant. None of the other measures in the query is calculated, and in fact the cube doesn't have any calculated members. So what is Aggregate() actually trying to do here? Is this error message (again, in MDX!) completely misleading?
ADDITION: #whytheq in the answer below suggested creating the calculated measure using Aggregate, but creating it on a spare dimension hierarchy rather than in the Measures dimension. This works, but only if the cross-join with the [All] member of the selected "any old..." dimension is included.
Creating the measure there also makes it impossible to put the two (base) measures and the calculated measure on the same axis. If I try to do this:
{Measures.ThingoCount,Measures.WeekTotal,[Ages].[Age Key].WeekSummedTotal} ON 0,
I get the deeply-unhelpful error message:
Members, tuples or sets must use the same hierarchies in the function.
which, I think, translates to "I can't make a set using the , (UNION) function between members of Measures and members of [Ages].[Age Key] because they're members of different dimensions".
My conclusion, thanks to your informative answers, is that Aggregate() with a single argument is a tricky beast; I wonder why it was designed with the second argument optional?
I've also noted that trying to create my calculated member on my Ages dimension (only one hierarchy, only one attribute) gives me the misleading error message:
The 'Ages' dimension contains more than one hierarchy, therefore
the hierarchy must be explicitly specified.
unless I explicitly specify the hierarchy. MDX has so much potential, but the learning curve would be that much gentler if MS had put more effort into making it feed back errors properly.
What would this do? Would Aggregate aggregate the cube's default
measure over the set? Or the set Measures.Members? Or the set of other
measures specified on the 0 axis?
Aggregate function aggregates the set over the current measure for Measures dimension. And a measure is "current" if it is in scope. If a measure is not in scope, the default member from measures dimension is considered for aggregation.
A measure can be added to scope in many ways like
Having the measure on axes
with member [Customer].[Customer].abc as
aggregate([Customer].[Customer].members)
select [Customer].[Customer].abc on 0,
{[Measures].[Internet Sales Amount],[Measures].[Reseller Sales Amount]} on 1
from [Adventure Works]
In the above example the member abc was calcualted twice, once for each measure.
Using Subcube
with member [Customer].[Customer].abc as
aggregate([Customer].[Customer].members)
select [Customer].[Customer].abc on 0
from (select {[Measures].[Internet Sales Amount] } on 0 from [Adventure Works])
Having the measure in definition
with member [Customer].[Customer].abc as
aggregate([Customer].[Customer].members, [Measures].[Internet Sales Amount])
select [Customer].[Customer].abc on 0
from [Adventure Works]
In Where clause
with member [Customer].[Customer].abc as
aggregate([Customer].[Customer].members)
select [Customer].[Customer].abc on 0
from [Adventure Works]
where [Measures].[Internet Sales Amount]
As suggested by whytheq, have the member on some other dimension-hierarchy combo. Otherwise, the aggregate function would probably lead to the calculated member self-referencing itself.
Taking this section of the MSDN definition:
...this function aggregates each measure within the current query
context ...
each measure in the context of your script is the following:
{Measures.ThingoCount,Measures.WeekTotal,Measures.WeekSummedTotal}
Now Measures.WeekSummedTotal is a calculated members in the measures dimension - hence the error.
I'd imagine something like the following would function ok, where you use Aggregate to create a member in a dimension other than Measures?:
WITH
MEMBER [SomeSpareDim].[SomeSpareHier].WeekSummedTotal AS
Aggregate
(
[Days].[WeeksAndDays].CurrentMember.Children * [SomeDim].[SomeHier].[All]
)
SELECT
[SomeSpareDim].[SomeSpareHier].WeekSummedTotal ON 0
,[Days].[WeeksAndDays].[WeekName] ON 1
FROM DateGRoupingTest;
The above can be changed to show Aggregate being very useful:
WITH
MEMBER [Days].[WeeksAndDays].[Last3Weeks] AS
Aggregate
(
{
[Days].[WeeksAndDays].[Weekx]
,[Days].[WeeksAndDays].[Weeky]
,[Days].[WeeksAndDays].[Weekz]
}
)
SELECT
{Measures.ThingoCount,Measures.WeekTotal} ON 0
,{
//<< the following custom aggregated member will work for any measure, that is ON 0, via Aggregate
//it can be mixed up with the normal members of the same hierarchy like the following
[Days].[WeeksAndDays].[Last3Weeks]
,[Days].[WeeksAndDays].[WeekName].members
} ON 1
FROM DateGRoupingTest;
I am new to MDX expressions and I am trying to create one that sums the value of a given measure filtered by dimensions.
In my database I have several different dimensions that have the same name: "Answer". To sum them up, I have created the query below:
WITH MEMBER Measures.Total as SUM ({[Activity].[Activity].&[14], [Activity][Activity].&[22]},
[Measures].[Activity time])
SELECT NON EMPTY [Measures].[Total] on COLUMNS from [My Analytics]
This query works, however I had to use the "&[14]" and "&[22]" statments that correspond to two different "Answer" dimensions.
Since I have more than two dimensions with the same name, is there a way to rewrite the query above in a way that I would select all these dimensions without having to add their unique ID? For example, I would re-write the query as something like this:
WITH MEMBER Measures.Total as SUM ({[Activity].[Activity].&["Answer"]},
[Measures].[Activity time])
SELECT NON EMPTY [Measures].[Total] on COLUMNS from [My Analytics]
Is this possible?
Thanks!
You can use the Filter function as following:
with
set [my-answers] as
Filter( [Activity].[Activity].members,
[Activity].[Activity].currentMember.name = 'Answer'
)
member [Measures].[Total] as Sum( [my-answers] )
...
I have created new measure that counts distinct policies (this measure is called FK Policy Distinct Count).
Then I created new calculated member called CountPolicyEndorsesNull which counts all policies from FK Policy Distinct Count using a filter:
(([Policy].[Endorses].&[0],[FK Policy Distinct Count]).
Than I did new calculated member called CountPolicy:
SUM(EXCEPT([Policy].[Policy Status].[Policy Status],[Policy].[Policy Status].&[Void]), [Measures].[CountPolicyEndorsesNull])
Next, I created a new member CountNewBound
SUM(
{
[Submission].[Tran Type].&[New], [Submission].[Tran Type].&[Developed]
},
[Measures].[CountPolicy]
)
And finally, YTDCountNewBound
SUM(YTD([Invoice Date].[Date Hierarchy].CurrentMember), [Measures].[CountNewBound])
Obviously, SUM function doesn't work in this case. Any idea how to make proper YTD count for calculated member?
Distinct count is a special measure which should be managed with a little more care. The rational behind this is that the when evaluating the measure a set of previous values is kept in memory. In order to improve performance, this structure is not passed and it's quickly converted to a scalar value.
Going back to your problem :
Distinct count can be evaluated over a tuple without problem, but you'll get in problems once you try to evaluate over a set of tuples. A possible, but costly and not always possible, is to create a hierarchy of values so you can convert your set in a member of a dimension.
In your case instead of using YTD([Invoice Date].[Date Hierarchy].CurrentMember) function using another hierarchy -> [Invoice Date].[YTD Date Hierarchy].
All this depends on the specific OLAP implementation you're using, but I guess holds true for mainly all OLAP vendors.