SSAS / MDX Query - Get month-by-month data for an item - ssas

I have a query:
SELECT
NON EMPTY { [Item].[123] } ON COLUMNS,
{ [Total Line Value] } ON ROWS
FROM [Sales Analysis]
This returns the total amount sold for an item called "123". What I'd like to do is split this up so that I'm able to see the total sold for each month of the calender year. Something like:
SELECT
NON EMPTY { [Time].[Year].[Calender 2011].Children, [Item].[123] } ON COLUMNS,
{ [Total Line Value] } ON ROWS
FROM [Sales Analysis]
But this doesn't work as I intend to do, I just cant get the query right. Any help would be appreciated, thanks.
EDIT:
I've also tried this, but to no avail:
SELECT
NON EMPTY { [Time].[Year].[Calender 2011].Children } ON COLUMNS,
{ [Total Line Value] } ON ROWS
FROM [Sales Analysis]
WHERE [Item].[123]

SELECT
NON EMPTY { [Time].[Year].[Calender 2011].Children } ON COLUMNS,
{ [Item].[123] } ON ROWS
FROM [Sales Analysis]
WHERE [Measures].[Total Line Value]

Your syntax for [Item].[123] looks odd - Is this shorthand? Normally for a single member the syntax would be [Dimension].[Attribute].[Item123]? I'd expect your query 3 to work as expected otherwise?

Use crossjoin:
SELECT
NON EMPTY {{[Time].[Year].[Calender 2011].Children} * {[Item].[123]}} ON COLUMNS,
{[Total Line Value]} ON ROWS
FROM [Sales Analysis]

Related

How can i use a subquery or (WITH)statment in MDX Query?

I have a CustomerToFactor as a Measure and Customer as a Dimension. Now I want to create a MDX code like this SQL code but I can't. because (WITH) statements has another meaning in MDX.
with Total_Customer(
select cus_id
,sum(ctf_price) cus_total_price
from dbo.Customer
join dbo.CustomertoFactor on cus_id = ctf_cus_id
group by cus_id
)
select cus_id
,cus_name
,ctf_date
,ctf_price
,(cus_total_price / 100 * ctf_price) as Price_pro_customer
from dbo.Customer
join dbo.CustomertoFactor on cus_id = ctf_cus_id
join Total_Customer on Total_customer.cus_id = dbo.Customer.cus_id
SELECT NON EMPTY { [Measures].[ctf_date]
,[Measures].[ctf_price]
, (?) Price_pro_customer
} ON COLUMNS
,NON EMPTY {[Customer].[Customer - cus_name].[Customer - cus_name].ALLMEMBERS}
FROM [CustomerToFactor]
Thanks for your Answers. but it doesn't work. Actually I want it to be grouped for every name you name. for Example: for the name Alex only the sum would have to be calculated for Alex(100+300 = 400) as well as Group by.
I do not really understand the point of the calculation :)
But anyway, in MDX you can have your own measures calculated like this:
WITH MEMBER [Measures].[Price_pro_customer] AS
(SUM([Measures].[ctf_price]) / 100 * [Measures].[ctf_price])
SELECT NON EMPTY { [Measures].[ctf_date]
,[Measures].[ctf_price]
,[Measures].[Price_pro_customer]
} ON COLUMNS
,NON EMPTY {[Customer].[Customer - cus_name].[Customer - cus_name].ALLMEMBERS}
FROM [CustomerToFactor]
I am not sure you'll get the same result as the SQL query though, since you have [Customer].[Customer - cus_name].[Customer - cus_name].ALLMEMBERS on the rows which basically does a GROUP BY on the customer name.
So if in the table you had several rows for the same customer the output of MDX query should be 1 row for each customer. The SUM([Measures].[ctf_price]) is also different since it sums over all customers
I think you should create a date dimension reference to ctf_date.
Then your mdx should be as below:
WITH MEMBER [Measures].[Price_pro_customer] AS
SUM([DimDate].[ctf_date].[All], [Measures].[ctf_price]) / 100 * [Measures].[ctf_price]
SELECT NON EMPTY {
[Measures].[ctf_price] ,
[Measures].[Price_pro_customer]
} ON COLUMNS ,
NON EMPTY {[Customer].[Customer - cus_name].[Customer - cus_name].ALLMEMBERS *
[DimDate].[ctf_date].[ctf_date].ALLMEMBERS} ON ROWS
FROM [CustomerToFactor]

Truly Distinct Count in Hierarchy (MDX)

I am working with data in an OLAP-cube setup. I am wanting to display all Math Student Groups with the distinct student count for each group. Students get placed into a Math group based on how they scored on their math placement exam. They also get placed in every Math group lower than the one they placed into. (placed into Math 106, also a member of Math 105, 104, 103, 102, 101 and 100) Currently I am able to show only Math Groups on my rows and Distinct Students as a measure on the columns. The counts that display are only distinct per row and not for the entire report. So Math 100 group is displaying the count of all students in Math groups, not just Math 100.
WITH
/*- Qv6.0.3431.1887 -*/
SELECT
NON EMPTY
{
DISTINCT ( { [Measures].[Distinct Students] } )
}
PROPERTIES PARENT_UNIQUE_NAME, MEMBER_KEY, MEMBER_TYPE
ON COLUMNS,
NON EMPTY
{
{ [Student].[Student].[All Students] }
* { { { DISTINCT(
{ { FILTER(
{ { FILTER(
{ DESCENDANTS( [Student Group].[Student Group].[All Student Groups] , [Student Group].[Student Group].[Student Group]) } , InStr(1,IIF( ISERROR( [Student Group].[Student Group].CURRENTMEMBER.MEMBER_CAPTION ),"", [Student Group].[Student Group].CURRENTMEMBER.MEMBER_CAPTION ) , "Math") <> 0
) }
} , InStr(1,IIF( ISERROR( [Student Group].[Student Group].CURRENTMEMBER.MEMBER_CAPTION ),"", [Student Group].[Student Group].CURRENTMEMBER.MEMBER_CAPTION ) , "eligible") <> 0
) }
} ) }
} }
}
PROPERTIES PARENT_UNIQUE_NAME, MEMBER_KEY, MEMBER_TYPE
ON ROWS
FROM [Student Term]
WHERE ( [Terms].[Terms].[Term].&[138] )
CELL PROPERTIES FORMATTED_VALUE, VALUE, FONT_NAME
Here is a screenshot of the output:
Math Groups Student counts
I have tried searching all over here but was not successful in finding anything to help. I am by no means proficient in MDX, the reporting tool we use creates it based on what items we choose in the report builder (drag and drop mostly). The tool does allow you to create custom measures and elements using MDX. I really appreciate all assistance and please let me know if more information is needed.
Thanks!
====UPDATE 1-FEB-2017=======
thanks for your reply. I am finally getting to work on this again. I created custom measures in our front-end tool based on your code. I changed the [Measures].[StudentsCount] to [Measures].[Distinct Students] to match an available measure. If I select the 'StudentsCountDC' custom measure and run the report it returns nothing. If i select the 'IsStudentsTop' custom measure the counts it returns are extremely large like it isn't running for the selected term. Here is the new MDX that was generated after I ran the report with the newly created custom measure, 'StudentsCountDC'.
WITH
/*- Qv6.0.3431.1887 -*/
SELECT
NON EMPTY
{
DISTINCT ( { [Measures].[#~~2d0c2a98-fed9-4797-a573-170d3e450e4c~~#] } )
}
PROPERTIES PARENT_UNIQUE_NAME, MEMBER_KEY, MEMBER_TYPE
ON COLUMNS,
NON EMPTY
{
{ [Student].[Student].[All Students] }
* { [#~~9faf06d9-a022-493d-9dfd-dadd55793c37~~#] }
}
PROPERTIES PARENT_UNIQUE_NAME, MEMBER_KEY, MEMBER_TYPE
ON ROWS
FROM [Student Term]
WHERE ( [Terms].[Terms].[Term].&[136] )
CELL PROPERTIES FORMATTED_VALUE, VALUE, FONT_NAME
screenshots of new measures: IsStudentsTop & StudentsCountDC measures
Thanks again for your help!
It's a bit tricky, I personally haven't tested it yet. Hope, you'll get the point:
with
Member [Measures].[StudentsCountDC] as
SUM(
[Student].[Student].[Student].Members,
IIF(
not [Measures].[IsStudentsTop]
and
[Measures].[StudentsCount],
1,
NULL
)
)
Member [Measures].[IsStudentsTop] as
SUM(
{[Student Group].[Student Group].PrevMember:NULL},
[Measures].[StudentsCount]
)
IsStudentsTop checks whether StudentsCount exists in the upper groups (ordered by your attribute). StudentsCountDC checks if the current student has empty IsStudentsTop and StudentsCount is non empty, then returns 1 for each student, else returns Null.

Running total only covering range of cells with data

Using the illustrated mockup
(Note not all DimB members show so the total for DimA is larger than the sum of the displayed DimB, ignore this):
Query is showing (months,revenue) on 0, (dima,dimb) on 1 from cube
I would like some assistance in creating the calculated member that would calculate the running total across "Months" here (not a real time dimension).
Earlier i was using this one, but it was wrong on so many levels:
[Measures].[Accumulated Revenue] =
IIF(
([DimMonths].[Months].CurrentMember,[Measures].[Revenue]) = 0
AND ([DimMonths].[Months].CurrentMember.NextMember,[Measures].[Revenue]) = 0
,
IIF(
AGGREGATE({
[DimMonths].[Months].CurrentMember :
[DimMonths].[Months].Parent.LastChild
},[Measures].[Revenue]) = 0
,
NULL
,
Aggregate( {
[DimMonths].[Months].Parent.FirstChild :
[DimMonths].[Months].CurrentMember.PrevMember
}
,[Measures].[Revenue])
)
,
Aggregate( {
[DimMonths].[Months].Parent.FirstChild :
[DimMonths].[Months].CurrentMember
}
,[Measures].[Revenue])
)
Sounds like a job for a "scoped assignment". Basically, using a scoped assignment, you can overwrite the value of your calculated measure along the [Member_DimA_01] slice so that these values represent a running total instead of a sum of children.
Here's a good tutorial from Chris Webb on scoped assignments to help get you started...
Edit: here's a template for the running total calculation...
WITH
SET [Months] AS
{
[Date].[Calendar Month].&[2011 - Jan]
:
[Date].[Calendar Month].&[2011 - Dec]
}
MEMBER [Measures].[Running Total] AS
SUM(
{
[Date].[Calendar Hierarchy].[Calendar Month].&[2011 - Jan]
:
[Date].[Calendar Hierarchy].CurrentMember
}
,[Measures].[Revenue]
)
SELECT
NON EMPTY{
[Months]
} ON 0,
NON EMPTY{
[DimA].[Member].Allmembers *
[DimB].[Member].Allmembers
} ON 1
FROM
[<<cube name>>]
WHERE
[Measures].[Revenue Running Total]

MDX using except doesn't work

I have the following Problem:
Select
{
[Measures].[PerformanceTotalYtd]
} on columns,
Non Empty{
Except(([Desk].[DeskName].[Trade].Members,[Time].[Year-Month-Day].[Day].&[2012]&[1]&[10]),([Desk].[DeskName].[Trade].Members,[Time].[Year-Month-Day].[Day].&[2012]&[1]&[09]))
} on rows
from [Cube]
where ([Entity].[Entity].&[9], [Audience].[View].&[GOD])
It exists a Dimension with the Name Desk. This Dimension has a Hierarchy with the name DeskName. The lowest Level ist Trade.
Desk: -Total -Segment -BusinessArea -Department -4th Level Portfolio -Desk -Trade
With the Query showing below, i want to show all Trades, that have the Measure "PerformanceTotalYtd" != NULL on the Date of 2012/01/10 except the Trades with the Measure "PerformanceTotalYtd" != NULL on the Date of 2012/01/09 !
Example:
Trades with Measure PerformanceTotalYtd on the 2012/01/10:
ABC 12,99
DEF 3,22
GHI 55,60
Trades with Measure PerformanceTotalYtd on the 2012/01/09:
ABC 80,00
DEF 8,78
I want the following Result because the Trade "GHI" doesn't exists on the 2012/01/09 and is new:
GHI 55,60
My Query showing below have this result:
ABC 12,99
DEF 3,22
GHI 55,60
It doesn't delete the existing Trades from the 2012/01/09.
I have a Solution in SQL but want to make it in MDX:
SELECT DD.Code, Sum(PerformanceTotalYtd) as TOTAL
FROM [Reporting_DB].[Star].[Fact_PerformanceTotal] FIS
inner join Star.Dimension_Desk DD on FIS.DeskID = DD.DeskID
WHERE FIS.TimeID = 20120110 and FIS.EntityID = 9 AND DD.Code not in ( SELECT DD.Code
FROM [Reporting_DB_HRE].[Star].[Fact_PerformanceTotal] FIS inner join Star.Dimension_Desk DD on FIS.DeskID = DD.DeskID WHERE FIS.TimeID = 20120109 and FIS.EntityID = 9 group by DD.Code)group by DD.Code
Can anybody help me please? I can't find a solution.
Sorry for my bad english!
Alex
I have found a similar example in the Adventure Works cube:
The set {[Customer].[City].&[Bell Gardens]&[CA], [Customer].[City].&[Bellevue]&[WA], [Customer].[City].&[Bellflower]&[CA]} has 3 values for [Measures].[Internet Sales Amount] in [Date].[Calendar Year].&[2002], and only 2 values in [Date].[Calendar Year].&[2004]. So we need to show measure value for member in 2002 where measure value == null in 2004.
The next MDX query achieves the desired result:
with set S as '{[Customer].[City].&[Bell Gardens]&[CA], [Customer].[City].&[Bellevue]&[WA], [Customer].[City].&[Bellflower]&[CA]}'
select
[Measures].[Internet Sales Amount] on 0,
non empty { Filter(S, IsEmpty(([Date].[Calendar Year].&[2004], [Measures].[Internet Sales Amount]))) } on 1
from [Adventure Works]
where ([Date].[Calendar Year].&[2002])
I tried to modify your example accordingly, but can't test it. Here it is:
select
{ [Measures].[PerformanceTotalYtd] } on 0,
non empty { Filter([Desk].[DeskName].[Trade].Members, IsEmpty(([Time].[Year-Month-Day].[Day].&[2012]&[1]&[09], [Measures].[PerformanceTotalYtd]))) } on 1
from [Cube]
where ([Entity].[Entity].&[9], [Audience].[View].&[GOD], [Time].[Year-Month-Day].[Day].&[2012]&[1]&[10])
In short: use Filter instead of Except.
I have the Solution for my Problem. Following Query shows the same Result as the Query of Dmitry Polyanitsa! Have a nice Day guys!
with
set [Trades Today] as NonEmpty([Desk].[DeskName].[Trade].Members, ([Measures].[PerformanceTotalYtd], [Time].[Year-Month-Day].[Day].&[2012]&[1]&[10]))
set [Trades Yesterday] as NonEmpty([Desk].[DeskName].[Trade].Members, ([Measures].[PerformanceTotalYtd], [Time].[Year-Month-Day].[Day].&[2012]&[1]&[9]))
set [Trades Difference] as Except([Trades Today], [Trades Yesterday])
Select
{
[Measures].[PerformanceTotalYtd]
} on columns,
Non Empty{
[Trades Difference]
} on rows
from [Cube]
where ([Entity].[Entity].&[9], [Audience].[View].&[GOD])

MDX - TopCount plus 'Other' or 'The Rest'

I have created an MDX query which calculates the TOP 10 ZipCodes (according to my Patient Stay measure) as such:
WITH
MEMBER [Discharge Date].[Y-M-D].[ Aggregation] AS 'AGGREGATE( EXISTING { [Current Month] } )', SOLVE_ORDER = 0
SELECT
NON EMPTY { [Measures].[Patient Stays] }
ON COLUMNS,
TOPCOUNT({ ORDER( HIERARCHIZE( { [Patient].[ByZipcode].[All].CHILDREN } ), ( [Measures].[Patient Stays] ), BDESC ) }, 10)
ON ROWS
FROM [Patient Stay]
WHERE ( [Discharge Date].[Y-M-D].[ Aggregation], [Facility].[ByAffiliation].CURRENTMEMBER, [Facility].[ByRegion].CURRENTMEMBER )
This query is used to populate a PerformancePoint 100% Stacked Bar chart. The client has asked that since this is a !00% based chart, we lump the rest of the zip codes into an "Other" field, such that there should be 11 values: one for each of the top 10, and an eleventh which is a sum of the remaining Zip Codes.
I am an extreme novice to MDX, but this doesn't souund like it should be impossible. Does anyone have any ideas or suggestions?
I'll do my best with untested code, so here goes:
WITH
MEMBER [Discharge Date].[Y-M-D].[ Aggregation] AS 'AGGREGATE( EXISTING { [Current Month] } )', SOLVE_ORDER = 0
SET [Top10ZipCodes] AS
(TOPCOUNT({ ORDER( HIERARCHIZE( { [Patient].[ByZipcode].[All].CHILDREN } ), ( [Measures].[Patient Stays] ), BDESC ) }, 10))
MEMBER [Patient].[ByZipCode].[OtherZipCodes] AS
(AGGREGATE({EXCEPT([Patient].[ByZipCode].Members, [Patient].[ByZipCode].[Top10ZipCodes])}))
SELECT
NON EMPTY { [Measures].[Patient Stays] }
ON COLUMNS,
{[Top10ZipCodes], [Patient].[ByZipCode].[OtherZipCodes]}
ON ROWS
FROM [Patient Stay]
WHERE ( [Discharge Date].[Y-M-D].[ Aggregation], [Facility].[ByAffiliation].CURRENTMEMBER, [Facility].[ByRegion].CURRENTMEMBER )
What this does is creates a set of your top 10 ZIP codes, and then aggregates (different than sum!!!) all the ZIP codes, with the exception of your top 10.
Also, if this is a common set (top 10 ZIP codes), you may want to make a set on the cube, where you can reuse it ad nauseum, without having to change every MDX query you have.
Cheers,
Eric