MDX: Distinct Count of members summarized by another dimension - mdx

From my cube, I am trying to get a distinct count of all non-empty [ID].[FullID]s but summarized by [Underlying].
I know that, for example, there are two IDs for [Underlying].[Underlying1] at this particular WHERE slice and I can see this by running the below MDX query, which clearly gives me a row for each (but a zero count?):
Results:
Underlying | FullID | CountOf
------------------------------
Underlying1 | ID1 | 0
Underlying1 | ID2 | 0
...
Code:
WITH
MEMBER CountOf AS
DistinctCount([ID].[FullID].Children)
SELECT
NON EMPTY {[Underlying].Children * [ID].[FullID].Children
} ON ROWS,
NON EMPTY {CountOf
} ON COLUMNS
FROM [MyCube]
WHERE ([Time].&[2018-11-27T00:00:00],
[Factor].[FactorName].[FACTOR1],
[Factor].[FactorType].[FACTORTYPE1]
[Location].[Location1]
)
However when I remove the * [ID].[FullID].Children I don't get what would like:
What I want:
Underlying | CountOf
---------------------
Underlying1 | 2
...
What I get:
Underlying | CountOf
---------------------
Underlying1 | 24
...
There is clearly something else going on here to give me a 24 count, but I cannot figure it out...

You are getting 24 because you measure is counting the members in [ID].[FullID].Children. What i understand is that you want to count the number of [ID].[FullID] who have a fact value availabe against them for [Underlying].Children. So your code should be like this
WITH
MEMBER CountOf AS
Count(
nonempty(([Underlying].currentmember,[ID].[FullID].Children),
[Measures].[ConnectingMeasure])
)
SELECT NON EMPTY {[Underlying].Children } ON ROWS,
NON EMPTY {CountOf} ON COLUMNS
FROM [MyCube]
WHERE ([Time].&[2018-11-27T00:00:00],[Factor].[FactorName].[FACTOR1],
[Factor].[FactorType].[FACTORTYPE1],[Location].[Location1]
)
Here is a sample of what you want to do in adventureworks. I am trying to count all Promotion, that are present for a product based on the internet sales data.
WITH
MEMBER CountOf AS
count(nonempty( ([Product].[Product].currentmember, [Promotion].[Promotion].children) ,[Measures].[Internet Sales Amount]))
SELECT
NON EMPTY {CountOf} ON COLUMNS,
NON EMPTY {
([Product].[Product].Children )
} ON ROWS
FROM [Adventure Works]
//Base query to understand what is counted
WITH
MEMBER CountOf AS
Count(nonempty( ([Product].[Product].currentmember, [Promotion].[Promotion].children) ,[Measures].[Internet Sales Amount]))
SELECT
NON EMPTY [Measures].[Internet Sales Amount] ON COLUMNS,
NON EMPTY {
([Product].[Product].Children,[Promotion].[Promotion].children )
} ON ROWS
FROM [Adventure Works]

Related

MDX script - mix empty and non empty on the same axis

I would like to ask your help to understand the main logic of MDX query. I would like to query different dimensions from the cube. But: in some case I would like to hide the NULL values, but in other dimension it is still needed. In my case I would like to provide date weeks and it dates for every day within the time period. (Even if it has no data) The content would be order number, position number and company and of course the KPI: OTD_customer. I tried many times to fix the null value issue, but I'm beginner on MDX. I tried to use NON EMPTY keyword and also Nonempty function, but still don't have the wished result. One more complicated thing is to filter the date for time period: based on actual day the last 15 weeks. (this part is working fine)
> SELECT NON EMPTY
> { [OTD_customer_new] } ON COLUMNS, NON EMPTY
> {
> (
> (( strtoset("LASTPERIODS(15,([Date - Plan Delivery Date].[Calendar Week].&[" + left(ltrim("2017 KW 10"),4) +" KW " + right(ltrim("2017 KW 10"),2) + "]) ) ")
> , [Order Number].[Order Number].[Order Number].ALLMEMBERS
> , [Position Number].[Position Number].[Position Number].ALLMEMBERS
> ,[Date - Plan Delivery Date].[Day of the Week].ALLMEMBERS
> ,[Group Structure].[Group Structure].ALLMEMBERS
> ) )
> *
> ([Date - Plan Delivery Date].[Date].[All].FirstChild:
> tail
> ( filter
> ( [Date - Plan Delivery Date].[Date].[All].Children,
> [Date - Plan Delivery Date].[Date].CurrentMember.Name <= Format(Now(), "yyyyMMdd")
> ), 1
> ).item(0)
> ))
> }
> ON ROWS
> FROM [ProductionCube]
Shall I use the filter in where condition? what is the best way to query the result from the cube? When it will be in normal relation database I would use a simple joins for this purpose.. But here in MDX I don't see the possibility with left and inner joins in script. Based on my understanding the hole axis may have the possibility to filter the null values. Do you have any idea? (thank you for reading) Current result example can be found here
The Non Empty function designed to filter empty axes (when your output is calculated). The NonEmpty function does the calculation of set. So, if you run:
Non Empty {Set1} * {Set2}
You'll get only crossjoined non-empty records.
If you run:
NonEmpty({Set1} * {Set2}, [Measures].[NonEmptyMeasure])
You'll get the same result, but the mechanic is a bit different. If you want to filter only specific sets you may use NonEmpty around these sets:
{Set1} * NonEmpty({Set2}, [Measures].[NonEmptyMeasure])
Set1 won't be filtered. Nonetheless, all members of Set1 will crossjoined with all non-empty members of Set2. Most likely that's not what you want.
You have many extra attributes joined to your date. What do expect them to return for empty records? I may guess you want to return All member, say, Set1 is a date set and Set2 is a company set:
NonEmpty({Set1} * {Set2}, [Measures].[NonEmptyMeasure]) + { {Set1} - NonEmpty({Set1}, [Measures].[NonEmptyMeasure])} * {Set2}.Item(0).Parent
Explanation:
1. NonEmpty({Set1} * {Set2}, [Measures].[NonEmptyMeasure]) -- returns non-empty records
2. {Set1} - NonEmpty({Set1}, [Measures].[NonEmptyMeasure]) -- returns empty dates
3. {Set2}.Item(0).Parent -- returns All member
The result will look like the following:
|=====================================|
| 2016 week 51 | Company1 | 1 |
| 2016 week 51 | Company2 | 1 |
| 2016 week 51 | Company3 | 1 |
| 2016 week 52 | All companies | NULL |
=======================================
Is it the wished result?

Not allow any null values in resultset MDX

I want to exclude any rows where there is a null value in my MDX query. Sounds simple enough:
SELECT
NON EMPTY{
....
}
ON 0
etc...
However, one of my columns has values even though the other ones only contain null vales.
Example:
Area | ComputerSales | Areadirector
WA (Null) Steve
NY 21312 Mary
How do I remove the first row, where there is a (null) value?
You could use HAVING
SELECT
{
[Measures].[Computer Sales]
,[Measures].[Areadirector]
} ON 0
,[AreaDimension].[Area].[Area] HAVING
(NOT
IsEmpty([Measures].[Computer Sales])) ON 1
FROM [YourCube];
Or make the set in a WITH clause first:
WITH
SET [S] AS
NonEmpty
(
[AreaDimension].[Area].[Area]
,[Measures].[Computer Sales]
)
SELECT
{
[Measures].[Computer Sales]
,[Measures].[Areadirector]
} ON 0
,[S] ON 1
FROM [YourCube];
Second approach is probably more efficient.
You can use for example FILTER and ISEMPTY function
SELECT
[Measures].[Fac Count] on 0,
FILTER(
[Time].[Date Key].children,
NOT ISEMPTY([Measures].[Fac Count])
)
on 1
FROM
[Test]
this simple query returns only date keys that Fac Count measure has non empty value.

select data from olap MDX query

Please help to understand how MDX query works.
I have connected to cube using excel and construct a mdx query. In short finally I need to get the table like this:
12.01.2015
+-------+-------+-------+-----+-------+------
| 00:00 | 01:00 | 02:00 | ... | 23:00 | TOTAL
--------+-------+-------+-------+-----+-------+------
Ivan | null | 3 | null | ... | 12 | 38
Pert | 3 | 8 | null | ... | null | 125
Sidor |
We see the Date, Time (hour), FIO (Ivan, Petr etc) and values.
The cube has dimensions: Dim Date, Dim Hour, Dim Users
I trying to get MDX query from excel but I cant understand how to modify it to get result I need. Here is the request (formatted):
SELECT NON EMPTY
CrossJoin(
Hierarchize(
DrilldownMember(
{
{
DrilldownMember(
{
{
DrilldownLevel
(
{[Dim Date].[Даты YMD].[All]}
)
}
},
{[Dim Date].[Даты YMD].[Year Name].&[2015]}
)
}
},
{[Dim Date].[Даты YMD].[Year Name].&[2015].&[5]}
)
),
Hierarchize(
{
DrilldownLevel(
{[Dim Hour].[Hour Key].[All]}
)
}
))
DIMENSION PROPERTIES PARENT_UNIQUE_NAME,
[Dim Date].[Даты YMD].[Date Key].[Month Name],[Dim Date].[Даты YMD].[Date Key].[Year Name] ON COLUMNS ,
NON EMPTY
Hierarchize(
{
DrilldownLevel(
{[Dim Users].[FIO].[All]}
)
}
)
DIMENSION PROPERTIES PARENT_UNIQUE_NAME ON ROWS FROM
(
SELECT ({[Dim Date].[Даты YMD].[Year Name].&[2015].&[5]}
)
ON COLUMNS
FROM [Dwh Sorting])
WHERE ([Measures].[Fact Table Count]) CELL PROPERTIES VALUE,
FORMAT_STRING,
LANGUAGE,
BACK_COLOR,
FORE_COLOR,
FONT_FLAGS
It gets data for May 2015. My goal is to get a long table (with a lot of columns) like I showed. With one or more months.
Excel code that is autogenerated adds a lot of extra "bits".
Getting rid of the extra bits I'm guessing at something like the below. This script should give you lots of columns - assuming data for every hour in 2015 you should end up with 24 columns for every day in 2015!
The reason I say "guessing" as we do not know the hiearchical structure of your cube:
SELECT
NON EMPTY
Descendants
(
[Dim Date].[Даты YMD].[Year Name].&[2015]
,[Dim Date].[Даты YMD].[Date] //<<this assumes there is a level in Dim date called Date
)
*
{[Dim Hour].[Hour Key].MEMBERS} ON COLUMNS
,NON EMPTY
[Dim Users].[FIO].MEMBERS ON ROWS
FROM [Dwh Sorting]
WHERE
[Measures].[Fact Table Count];
If you need just the hours for a range of dates then try the : operator. You will not need to apply the Descendants function in this case:
SELECT
NON EMPTY
(
[Dim Date].[Даты YMD].[Date Key].[2014-01-02]
:
[Dim Date].[Даты YMD].[Date Key].[2015-02-10]
)
*
{[Dim Hour].[Hour Key].MEMBERS} ON COLUMNS
,NON EMPTY
[Dim Users].[FIO].MEMBERS ON ROWS
FROM [Dwh Sorting]
WHERE
[Measures].[Fact Table Count];

How can I select top 25 customers ordered by amount descending, for each dept?

I want top 25 customers ordered by amount descending, for each dept. like:
Dept|Customer|Amt
1 cust_1 5000
cust_2 2000
.
.
.
2 cust_26 6000
cust_27 3000
.
.
3
.
.
7
What I have tried so far is:
SELECT
NON EMPTY { [Measures].[Amount] } ON COLUMNS ,
NON EMPTY {
[Customer].[DEPT].[DEPT]*
ORDER(
TOPCOUNT([Customer].[Customer].[Customer],25,[Measures].[Amount]),
[Measures].[Amount], DESC)
}
FROM [cube]
I am getting result but not like 25 for each dept, though I have proper data.
Your second term of the cross join for the rows (ORDER(TOPCOUNT(...))) is not aware of the first ([Customer].[DEPT].[DEPT]). You should use Generate for this, as it loops over the departments, and thus allows you to put the current department into the first argument of the TOPCOUNT:
SELECT
NON EMPTY { [Measures].[Amount] } ON COLUMNS ,
NON EMPTY
Generate([Customer].[DEPT].[DEPT],
TOPCOUNT({[Customer].[DEPT].CURRENTMEMBER}
*
[Customer].[Customer].[Customer],
25,
[Measures].[Amount]
)
)
FROM [cube]
Also note that you do not need to order the result of TOPCOUNT descending, it is already ordered this way.

Fetching Previous Member while using order function in MDX

I have a mdx query which returns "productCode" and "Product share of total Sales" as a result.Also i need that query be sorted on "Product share of total Sales" (Decs)
So I came up with following MDX Query
WITH MEMBER [Measures].[Contribution] AS
Format(
IIF(
IsEmpty([Measures].[Detail_Net_Sales]),
0,
[Measures].[Detail_Net_Sales]
)/
[Measures].[SumTotalPayable]
)
SELECT
{[Measures].[Contribution]}
ON COLUMNS,
Order(
[DIMProduct].[ProductCode].[ProductCode].AllMEMBERS,
[Measures].[Contribution],
BDESC
)
ON ROWS
FROM [Model] }
the problem is when i also want to have Previous Contribution for each productcode
i wrote down somthing like this :
WITH MEMBER [Measures].[Contribution] AS
Format(iif(IsEmpty([Measures].[Detail_Net_Sales]),0,[Measures] [Detail_Net_Sales])/[Measures].[SumTotalPayable] )
MEMBER [Measures].[test]
AS
([Measures].[Contribution], [DIMProduct].[ProductCode].CurrentMember.PrevMember)
SELECT { [Measures].[Contribution] ,[Measures].[test]} ON COLUMNS
, Order([DIMProduct].[ProductCode].[ProductCode].AllMEMBERS ,[Measures]. [Contribution],BDESC)ON ROWS
FROM [Model]
but the above code will return previous Contribution without desire order.
do you have any idea how can i fix this?
Edit :
I want to have the Contribution of the previous row base on my sort and also have the test measure base on my prior sort,like the below table:
ProductCode Contribution Test
----------- ------------ ----
123 17.56 null
332 17.30 17.56
245 16 17.30
656 15.90 16
but what i get is like this :
ProductCode Contribution Test
----------- ------------ ----
123 17.56 17.30
332 17.30 16
245 16 Null
656 15.90 17.30
WITH MEMBER [Measures].[Contribution] AS
Format(
IIF(
IsEmpty([Measures].[Detail_Net_Sales]),
0,
[Measures].[Detail_Net_Sales]
)/
[Measures].[SumTotalPayable]
)
SET SortedProducts AS
Order(
[DIMProduct].[ProductCode].[ProductCode].AllMEMBERS,
[Measures].[Contribution],
BDESC
)
MEMBER [Measures].[PrevContribution] AS
(SortedProducts.Item(
Rank([DIMProduct].[ProductCode].CurrentMember, SortedProducts) - 2)
.Item(0),
[Measures].[Contribution])
SELECT
{[Measures].[Contribution], [Measures].[PrevContribution]}
ON COLUMNS,
SortedProducts
ON ROWS
FROM [Model] }
Your definition of the test measure uses the order of members as defined in the cube (alphabetically, if you did not define a custom order). But you need the order by Contribution, so I defined that as a named set containing the members in this order. Then I mis-used the Rank function which gives you the position of a tuple in a set. As the rank of the first member is 1, and I use the Item function to get a tuple within the set - which starts numbering the tuples with zero -, and we have to go one member back, you need the - 2, and finally, we need another Item(0) to get a member from the tuple.