I have a SQL Server Analysis Services cube ( Multidimensional). This cube represents Survey feedback. A student gives feedback on course for a given term (period of time ). There are 19 questions with a score from 1 to 5 and I try to get the median of these answers.
Just to precise, I am looking at the median of answer for each {Question, Course} just for one period of time ( term).
My cube model looks like this :
And the query I am running is :
with calculated member [Median] as
MEDIAN(existing NONEMPTY([Course].[COURSE NAME].children*[Survey
Question].[SURVEY QUESTION NUMBER].children),[Measures].[NUMERIC
RESPONSE])
Select non EMPTY{[Course].[COURSE NAME].children} on rows,
NON EMPTY{[Survey Question].[SURVEY QUESTION NUMBER].children*{[Measures].
[NUMERIC RESPONSE],[Median]}} on columns
from [EDW]
where [Term].[TERM].&[5515]
The result doesn't show anything on the Median as if it was null.
If anyone has an idea around this issue I will love to hear it.
Regards
Vincent
This is your query with a couple of small changes - unfortunately not used Median before and I do not have AdvWks to test on so feeling around in the dark a little:
WITH
MEMBER [Measures].[MYMedian] AS
MEDIAN(
NONEMPTY(
[Course].[COURSE NAME].[COURSE NAME].MEMBERS
*[Survey Question].[SURVEY QUESTION NUMBER].[SURVEY QUESTION NUMBER].MEMBERS
,[Measures].[NUMERIC RESPONSE]
)
,[Measures].[NUMERIC RESPONSE]
)
SELECT
NON EMPTY
[Course].[COURSE NAME].children on rows,
NON EMPTY
[Survey Question].[SURVEY QUESTION NUMBER].children
*{
[Measures].[NUMERIC RESPONSE]
,[Measures].[MYMedian]
}
on columns
FROM [EDW]
WHERE [Term].[TERM].&[5515];
Related
Problem: I'm trying to write a MDX query that will show the first date a member has measure values.
Data obstacles:
1. I don't have access to the data warehouse/source data
2. I can't request any physical calcs or CUBE changes
Looking for: I know this goes against what a CUBE should be doing, but is there any way to achieve this result. I'm running into locking conflicts and general run time issues.
Background: After some trial and error. I have a working query but sadly it's only is practical when filtered for <10 employees. I've tried some looping but there are ~60k employee ids in the cube with each one having 10-20 emp keys (one for each change in their employee info).
//must have values for measure 1 or 2
WITH
set NE_measures as
{
[Measures].[measure1] ,
[Measures].[measure2]
}
//first date with measure values for each unique emp key
MEMBER [Measures].[changedate] AS
Head
(
NonEmpty([Dim Date].[Date].[Date].allMEMBERS, NE_measures)
).Item(0).Member_Name
SELECT non empty {[Measures].[changedate]} ON COLUMNS,
non empty [Dim Employee].[Emp Key].[Emp Key].allmembers ON ROWS
FROM [Cube]
Try this:
MEMBER [Measures].[changedate] AS
Min(
[Dim Date].[Date].[Date].allMEMBERS,
IIF(
NOT(ISEMPTY([Measures].[measure1]))
OR NOT(ISEMPTY([Measures].[measure2])),
[Dim Date].[Date].CurrentMember.MemberValue,
NULL
)
);
I’m assuming the KeyColumn or ValueColumn is more likely to sort properly than the name. So if MemberValue doesn’t work then try Member_Key.
The most efficient way of accomplishing this would be to add a date column in the fact table with measure 1 and measure 2 then create a AggregateFunction=Min measure on it. But you said you couldn’t change the cube so I didn’t propose that superior option.
I was wondering which of the following two queries is more performant?
Query 1:
SELECT NONEMPTY(CROSSJOIN({[Product].[Category].children},
{[Scenario].[Scenario].members}
)
) ON COLUMNS
FROM [Analysis Services Tutorial]
Query 2:
SELECT CROSSJOIN(NONEMPTY({[Product].[Category].children}),
NONEMPTY({[Scenario].[Scenario].members})
) ON COLUMNS
FROM [Analysis Services Tutorial]
I would say query 2 is more performant/optimized because first you take out all the unnecessary members and then crossjoin them. The first query you crossjoin everything and then take out the nulls. That would be my guess but I want somebody who can clear me up.
Edit 1 In response of comments of an answer
Lets say I add a measure as a second parameter, so it does not go to the "default measure". How could second query return values with null? I am specifying to crossjoin between nonempty members. And I just really dont see how the can return different results no matter the dimensions involved. To me they seemed pretty equivalent. What am I not seeing?
Query 1:
SELECT NONEMPTY(CROSSJOIN({[Product].[Category].children},
{[Scenario].[Scenario].members}
), [Total Internet Sales]
) ON COLUMNS
FROM [Analysis Services Tutorial]
Query 2:
SELECT CROSSJOIN(NONEMPTY({[Product].[Category].children},[Total Internet Sales]),
NONEMPTY({[Scenario].[Scenario].members},[Total Internet Sales])
) ON COLUMNS
FROM [Analysis Services Tutorial]
Edit 2
As the answer said the queries are not the same. I realized when #GregGalloway presented other scenario.
I did an excel with sample data so maybe someone can find it useful.
They aren't equivalent since both queries we will return different results. For example, against the real Adventure Works (not some tutorial version) these two queries return different results. Notice that the Clothing/Kentucky column shows null on the second query:
SELECT NONEMPTY(CROSSJOIN({[Product].[Category].children},
{[Customer].[State-Province].[State-Province].Members}
), [Measures].[Internet Sales Amount]
) ON COLUMNS
FROM [Adventure Works]
where [Measures].[Internet Sales Amount]
SELECT CROSSJOIN(NONEMPTY({[Product].[Category].children},[Measures].[Internet Sales Amount]),
NONEMPTY({[Customer].[State-Province].[State-Province].Members},[Measures].[Internet Sales Amount])
) ON COLUMNS
FROM [Adventure Works]
where [Measures].[Internet Sales Amount]
Note that the Scenario dimension doesn't relate to the Internet Sales measure group, I don't think. So that may not be a good example. I chose the Product dimension and the Customer dimension for my example.
As discussed (and as you updated in your question) NonEmpty() should always have a second parameter so it is clear what measure you are doing NonEmpty against. Your query should also mention a measure on one axis or the WHERE clause so that you're not returning some vague "default measure". I've included a WHERE clause with a measure in my examples.
Anyway, to answer your question... assuming the measure is a physical measure or a well optimized calculated measure that runs in block mode I wouldn't be surprised if Query 1 is faster. But it depends on the measure and the size of dimensions and the sparsity of the cube. This question is very theoretical and the two queries don't return equivalent results.
i have a huge table of cashflows that means there are +int values for income and -int values for outcome.
I have MeasureGroup for Sum the amount of money.
I now want to display not only the sum of money per month but also the sum of all the past time until the current month so like that:
Month MoneyAmount Total
1 20 20
2 -10 10
3 5 15
4 -10 5
So i know for the first part its just like
select [Measures].[Money] on 0,
[Date].[Month].Members on 1
From MyCube
but how can i add the sum column?
i thought about something like SUM( { NULL : [Date].[Month].CurrentMember } , [Measures].[Money] ) but that didnt work as well :(
In MDX, the total is already there. You do not have to do complex calculations to get it.
But it depends on your exact hierarchy structure how the All member is called. If you have a date user hierarchy named [Date].[Date], and it has a month level named [Date].[Date].[Month], then the all member of the hierarchy would probably be called something like [Date].[Date].[All]. If [Month] is an attribute hierarchy of the Date dimension, then the "all member" would probably be called [Date].[Month].[All]. In the latter case, the all member would already be the first member of the set [Date].[Month].Members. As you are asking the question, I am assuming this is not the case, and you are using a user hierarchy. Then you could change your MDX query to
select [Measures].[Money] on 0,
Union([Date].[Month].Members, { [Date].[Date].[All] }) on 1
From MyCube
Please note that you can change the name of the All member in the property settings of a dimension when designing an Analysis Services dimension, hence I cannot know the definitive name without knowing the details of this setting in your cube. So you might have to adapt the name of the all member.
You can find this name out in SQL Server Management Studio in an MDX window as follows: open the hierarchy that you are using, and then open the "Members" node, below which you should find the "All Member". You can drag this into your MDX statement, and the proper name will appear there.
As in a running sum?
You need a calculated measure, like this:
With Member [Measures].[Running Sum] as Sum( ( [Date].[Months].Members.Item(0) : [Date].[Months].CurrentMember ), [Measures].[Money])
Select [Date].[Months].Members on Rows,
{[Measures].[Money], [Measures].[Running Sum] } on Columns
From [MyCube]
I would like to calculate a Measure based on the current row.
Problem is I can't find a way to get the current row in a WITH MEMBER part.
WITH MEMBER [Measures].[Test] AS AVG(
NonEmptyCrossJoin(
FILTER(DESCENDANTS([Exigences].[ENVGR], [Levier], SELF),
[Exigences].CurrentMember.Name = 'Chemicals'),
DESCENDANTS([Organization].[Valeo].[Powertrain Systems], [entity], SELF)),
[Measures].[ProgressLevel])
SELECT {[Measures].[ProgressLevel], [Measures].[Test]} ON COLUMNS,
DESCENDANTS([Exigences].[ENVGR].[ENVGR-01.001], [Levier], SELF) ON
ROWS FROM [Exigences]
Chemicals is currently hard coded. That is for the example.
I would like in place of 'Chemicals' to have the current rows value.
So let's say those are the values rows will return 'Chemicals', 'Pharmacy', 'Test', I would like the [Measures].[Test] calculation to change.
Can MDX do that ? If so how can I get the current value.
I tried [Levier].CurrentMember.Name but I think it's conflicting with the [Exigences].CurrentMember.Name.
Any one has an idea ?
Thank you,
This has been taking a bit of effort but that's the advantage to have a nice gold badge. We're using the MDX Generate function and named sets (myCellSet & 2d example in link) :
Not sure this is going to work for your provider but you can try this one :
WITH MEMBER [Measures].[Test] AS AVG(
NonEmptyCrossJoin(
Generate( {[Exigences].CurrentMember} as MyCellSet,
FILTER(DESCENDANTS([Exigences].[ENVGR], [Levier], SELF),
[Exigences].CurrentMember.Name = MyCellSet.CurrentMember.Name)
)
,
DESCENDANTS([Organization].[Valeo].[Powertrain Systems], [entity], SELF)),
[Measures].[ProgressLevel])
I have a Cube which draws its data from 4 fact/dim tables.
FactCaseEvents (EventID,CaseID,TimeID)
DimEvents (EventID, EventName)
DimCases (CaseID,StateID,ClientID)
DimTime (TimeID,FullDate)
Events would be: CaseReceived,CaseOpened,CaseClientContacted,CaseClosed
DimTime holds an entry for every hour.
I would like to write an MDX statement that will get me 2 columns: "CaseRecievedToCaseOpenedOver5" and "CaseClientContactedToCaseClosedOver5"
CaseRecievedToCaseOpenedOver5 would hold the number of cases that had a time difference over 5 hours for the time between CaseReceived and CaseOpened.
I'm guessing that "CaseRecievedToCaseOpenedOver5" and "CaseClientContactedToCaseClosedOver5" would be calculated members, but I need some help figuring out how to create them.
Thanks in advance.
This looks like a good place to use an accumulating snapshot type fact table and calculate the time it takes to move from one stage of the pipeline to the next in the ETL process.
Query for AdventureWorks (DateDiff works in MDX):
WITH
MEMBER Measures.NumDays AS
'iif(ISEMPTY(([Delivery Date].[Date].CurrentMember
,[Ship Date].[Date].CurrentMember
,Measures.[Order Count]))
,null
, Datediff("d",[Ship Date].[Date].CurrentMember.Name
,[Delivery Date].[Date].CurrentMember.Name))'
SELECT
NON EMPTY {[Ship Date].[Date].&[63]
:[Ship Date].[Date].&[92]} ON COLUMNS,
NON EMPTY {[Delivery Date].[Date].&[63]
:[Delivery Date].[Date].&[92]}
* {[Measures].[NumDays]
, [Measures].[Order Count]} ON ROWS
FROM [Adventure Works]
Taken from: http://www.mombu.com/microsoft/sql-server-olap/t-can-i-have-datediff-in-mdx-265763.html
If you'll be using this member a lot, create it as a calculated member in the cube, on the Calculations tab if I remember right.