I need to filter this MDX result set - mdx

I am looking to filter the result set below such that I only show results where Dimension A Value 1 have a count of 1, regardless of the value of count for Dimension A Value 2
Dimension A Value 1 Dimension A Value 2
Entity ID Count Count
11 1
78 1
90 1
101 1
114 1
118 1
125 1
134 1
140 1
161 1
169 1
186 1 2
The filtered set would look like
Dimension A Value 1 Dimension A Value 2
Entity ID Count Count
11 1
78 1
90 1
101 1
118 1
125 1
140 1
161 1
169 1
186 1 2
the mdx is
WITH
SET [~COLUMNS] AS
{[Dimension A].[Dimension A].[Value 1], [Dimension A].[Dimension A].[Value 2]}
SET [~ROWS] AS
{[Entity].[Entity].[Entity ID].Members}
SELECT
NON EMPTY CrossJoin([~COLUMNS], {[Measures].[Count]}) ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [My Cube]
I've been playing around with Filter and NonEmpty but I'm new to MDX and my sql brain is hurting. I suppose this is probably trivial to someone with a lot of MDX under their belt but I'm failing. Be gentle this is my first question

You can try a HAVING clause:
WITH
SET [~COLUMNS] AS
{
[Dimension A].[Dimension A].[Value 1],
[Dimension A].[Dimension A].[Value 2]
}
MEMBER [Measures].[CountValue1] AS //<<<<this is new <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
(
[Measures].[Count],
[Dimension A].[Dimension A].[Value 1]
)
SELECT
NON EMPTY
CrossJoin(
[~COLUMNS]
, {[Measures].[Count]}
) ON COLUMNS,
NON EMPTY
[Entity].[Entity].[Entity ID].MEMBERS
HAVING [Measures].[CountValue1] = 1 //<<CHANGED TO NEW MEASURE
ON ROWS
FROM [My Cube];
If you can use HAVING rather than FILTER you will likely see a performance improvement - particularly if your scripts become more complex:
https://blog.crossjoin.co.uk/2006/01/04/the-having-clause/
Just to be complete the slower FILTER version would be this:
WITH
SET [~COLUMNS] AS
{
[Dimension A].[Dimension A].[Value 1],
[Dimension A].[Dimension A].[Value 2]
}
//>>>>>> following is new >>>>>>>>>>>>>>>>>>>>>
MEMBER [Measures].[CountValueNEW] AS
(
[Measures].[Count],
[Dimension A].[Dimension A].[Value 1]
)
SELECT
NON EMPTY
[~COLUMNS]
*{[Measures].[Count]}
ON 0,
NON EMPTY
FILTER(
[Entity].[Entity].[Entity ID].MEMBERS,
[Measures].[CountValueNEW] = 1
)
ON 1
FROM [My Cube];

Your query should be like
Select ([Dimension A].[AttributeHierarchy1].[AttributeHierarchy1],{[Measures].[Value1],[Measures].[Value2]}) on columns,
filter([Dimension B].[EntityID].[EntityID],[Measures].[Value1]=0)
on rows
from yourcube
However there can be an issue. For example your dimesnion has two values A and B, for a particular row , A,value1 =1 but B, Value1=0, this row will appear as A qulifies for it and B gets carried over.
Edit
Lets take an example I want to see Internet Sales for Bottles and Cages haveing sales more than 150$
My initial query
select
([Product].[Subcategory].[Subcategory],[Measures].[Internet Sales Amount]
)
on columns,
[Customer].[City].[City]
on rows
from
[Adventure Works]
Result
Now modify the query
select
([Product].[Subcategory].[Subcategory],[Measures].[Internet Sales Amount]
)
on columns,
filter
(
[Customer].[City].[City], [Measures].[Internet Sales Amount]>150
)
on rows
from
(select [Product].[Subcategory].&[28] on 0 from [Adventure Works])
Result

Related

MDX: Combining output for different criteria

I am new to MDX queries, and working in SSAS. I have two queries that are working suitably, but I want their output combined in a single result. The two queries differ in the cities selected by their where clauses, but they both come from the same cube and use the same measure.
A_to_B: Supplier city A to Consumer city B
SELECT { [Measures].[Quantity - Transactions] } ON COLUMNS,
{ [Tb Product].[Name].[Name].ALLMEMBERS } ON ROWS
FROM [Cube]
WHERE ([Tb Supplier].[City].&[A],
[Tb Consumer].[City].&[B])
B_to_A: Supplier city B to Consumer city A
SELECT { [Measures].[Quantity - Transactions] } ON COLUMNS,
{ [Tb Product].[Name].[Name].ALLMEMBERS } ON ROWS
FROM [Cube]
WHERE ([Tb Supplier].[City].&[B],
[Tb Consumer].[City].&[A])
Is there a way for the output of these queries to be produced side-by-side by Product, like this? In SQL I would have used a FULL OUTER JOIN, but I can't figure out the equivalent in MDX.
| | A_to_B | B_to_A |
| ProductA | 10 | 2 |
| ProductB | 100 | 0 |
| ProductC | 0 | 99 |
Simply move you Where statements to columns:
Select
{[Measures].[Quantity - Transactions]} *
{
([Tb Supplier].[City].&[B], [Tb Consumer].[City].&[A]),
([Tb Supplier].[City].&[A], [Tb Consumer].[City].&[B])
} on 0,
{[Tb Product].[Name].[Name].AllMembers} on 1
From [Cube]
You may create calculated members in order to unite two tuples:
With
Member [Tb Supplier].[City].[B2A] as
Aggregate([Tb Supplier].[City].&[B], [Tb Consumer].[City].&[A])
Member [Tb Supplier].[City].[A2B] as
Aggregate([Tb Supplier].[City].&[A], [Tb Consumer].[City].&[B])
Select
{[Tb Supplier].[City].[A2B],[Tb Supplier].[City].[B2A]} on 0
From [Cube]
Where ([Measures].[Quantity - Transactions])
I tested this script and it throws an exception:
SELECT
{[Measures].[Internet Sales Amount]}
*
{
{[Geography].[Geography].[Country].&[United States] * [Product].[Category].&[1]}
,{[Geography].[Geography].[Country].&[France] * [Product].[Category].&[3]}
} ON 0
,{[Date].[Calendar].[Date].&[20070801]} ON 1
FROM [Adventure Works];
This message:
Query (5, 7) The function expects a tuple set expression for the 1
argument. A string or numeric expression was used.
This is because you need to make either side of the cross-join specifically a set - without extra brackets it does not know this and throws an exception.
So this is the "perfect" version of the script:
SELECT
{[Measures].[Internet Sales Amount]}
*
{
{[Geography].[Geography].[Country].&[United States]} * {[Product].[Category].&[1]}
,{[Geography].[Geography].[Country].&[France]} * {[Product].[Category].&[3]}
} ON 0
,{[Date].[Calendar].[Date].&[20070801]} ON 1
FROM [Adventure Works];
I'd prefer to move the measure to the WHERE clause and also get rid of some of the redundant braces:
SELECT
{
{[Geography].[Geography].[Country].&[United States]}
*
{[Product].[Category].&[1]}
,
{[Geography].[Geography].[Country].&[France]}
*
{[Product].[Category].&[3]}
} ON 0
,[Date].[Calendar].[Date].&[20070801] ON 1
FROM [Adventure Works]
WHERE
[Measures].[Internet Sales Amount];
Translated to your cube:
SELECT
{
{[Tb Supplier].[City].&[B]} * {[Tb Consumer].[City].&[A]}
,
{[Tb Supplier].[City].&[A]} * {[Tb Consumer].[City].&[B]}
} ON 0
,[Tb Product].[Name].[Name].ALLMEMBERS ON 1
FROM [Cube]
WHERE
[Measures].[Quantity - Transactions];
Building on the others, here is one that replaces nulls with zeros in the output.
With
Member [Tb Supplier].[City].[B2A] as
Aggregate([Tb Supplier].[City].&[B], [Tb Consumer].[City].&[A])
Member [Tb Supplier].[City].[A2B] as
Aggregate([Tb Supplier].[City].&[A], [Tb Consumer].[City].&[B])
Member [Measures].[Quantity_Transactions] as
Iif( IsEmpty( [Measures].[Quantity - Transactions] ),
0,
[Measures].[Quantity - Transactions] )
SELECT
{ [Measures].[Quantity_Transactions] } *
{ [Tb Supplier].[City].[B2A],
[Tb Supplier].[City].[A2B] } on COLUMNS
, [Tb Product].[Name].[Name].ALLMEMBERS ON ROWS
FROM [Cube]

selecting max of distinct count when on multiple rows

I have a query that does a distinct count of accounts based on CB score. The problem I have is that an account can switch credit scores pretty often. So I would like to take the max credit score for a particular account.
Here is what I have that is returning higher than I want because of the switching of CB scores.
So for example account 1234 initially has a cb score of 500, then later has a cb score of 550. The account 1234 is now in both cb score ranges, but I only want to count them once.
WITH
MEMBER mem1 AS
Count
(
NonEmpty
(
[AccountID].[Account ID].[Account ID].MEMBERS
,measures.[Transaction Amount]
)
)
SELECT
NON EMPTY
{mem1} ON 0
,[CB Score].[RANGE].[RANGE] ON 1
FROM [CUBE]
WHERE [PROMO].[PROMO].&24
Try this:
WITH
MEMBER mem1 AS
Sum
(
[AccountID].[Account ID].[Account ID].MEMBERS
,IIF(
Not IsEmpty([Measures].[Transaction Amount])
And IsEmpty(Sum({[CB Score].[RANGE].CurrentMember.NextMember : null}, [Measures].[Transaction Amount])),
1,
Null
)
)
SELECT
NON EMPTY
{mem1} ON 0
,[CB Score].[RANGE].[RANGE] ON 1
FROM [CUBE]
WHERE [PROMO].[PROMO].&24
Basically the logic is to count the account if they had a transaction in that slice and if no greater CB Score range has a transaction.

MDX: Filtering repeated

I would like to write an MDX query that only show values when a specific repeated dimesions are repeatid more tha one.
That is my mdx query:
SELECT
NON EMPTY { [Measures].[Value] } ON COLUMNS,
NON EMPTY { ([Dim Result].[Sample Number].[Sample Number].ALLMEMBERS
* [Dim Parameter].[IdParameter].[IdParameter].ALLMEMBERS ) } ON ROWS
FROM [Cube]
the result its like that:
Sample Number IdParameter Value
1 3 5
1 4 6
2 3 2
3 4 0
What i want is to get only repeated sample number values like this:
Sample Number IdParameter Value
1 3 5
1 4 6
And remove the other values that are not repeated
Sample Number IdParameter Value
2 3 2
3 4 0
I donĀ“t know how i can do this, it is posible?
I write the next mdx:
SELECT NON EMPTY {[Measures].[Recuento Fact Result]} ON COLUMNS,
NON EMPTY { [Dim Result].[Sample Number].[Sample Number] } ON ROWS
FROM ( SELECT ({ [Dim Parameter].[IdParameter].&[420] , [Dim Parameter].[IdParameter].&[20] } ) ON COLUMNS
FROM [cube])
the result is that:
Sample Number Recount Fact Result
1 1
2 2
3 2
4 1
What i want is get only the Sample number where the recount is biger than 1
thanks for your help
My approach would be to create a calculated member which would hold number of distinct non-empty members per SampleNumber. Then filter out those tuples where the above count is not greater than 1.
UNTESTED (not near my system)
WITH MEMBER [Measures].CntParametersPerSampleNumber as
DistinctCount(
NonEmpty(
[Dim Parameter].[IdParameter].CHILDREN,
([Dim Result].[Sample Number].CURRENTMEMBER, [Measures].[Value])
)
)
SELECT
NON EMPTY { [Measures].[Value] } ON COLUMNS,
NON EMPTY {
Filter(
(
[Dim Result].[Sample Number].[Sample Number].ALLMEMBERS
*
[Dim Parameter].[IdParameter].[IdParameter].ALLMEMBERS
), [Measures].CntParametersPerSampleNumber>1
)
} ON ROWS
FROM [Cube]
You seem to have two separate questions.
The second question can be answered using the HAVING clause:
SELECT
NON EMPTY
{[Measures].[Recuento Fact Result]} ON 0,
NON EMPTY
{[Dim Result].[Sample Number].[Sample Number]}
HAVING [Measures].[Recuento Fact Result] > 1
ON 1
FROM
(
SELECT
({
[Dim Parameter].[IdParameter].&[420]
, [Dim Parameter].[IdParameter].&[20]
}) ON 0
FROM [cube]
)
For you first question you should be able to use the Filter function iteratively to detect if sample number is repeated:
WITH
SET [OrderedSampleNums] AS
Order(
[Dim Result].[Sample Number].[Sample Number].ALLMEMBERS ,
[Dim Result].[Sample Number].CurrentMember.Caption,
BASC
)
SET [RepeatedSampleNums] AS
Filter(
OrderedSampleNums ,
OrderedSampleNums.Item(
OrderedSampleNums.CurrentOrdinal-1
).Caption = [Dim Result].[Sample Number].CurrentMember.Caption
)
SET [NonRepeatedSampleNums] AS
Except(
OrderedSampleNums
,RepeatedSampleNums
)
SELECT
NON EMPTY
{[Measures].[Value]} ON 0,
NON EMPTY
[NonRepeatedSampleNums]
*
[Dim Parameter].[IdParameter].[IdParameter].ALLMEMBERS
ON 1
FROM [Cube];
Not tested but I could try to prototype something against the AdvWorks cube to explore further?

MDX query with TOPCOUNT between date range returning a top with some empty values

I'm using a MDX query to get the top 10 liked Products between two dates. Oddly, the result is composed by some Products with likes within that date range, and some without any likes at all. Here is the query:
SELECT
{ [Measures].[Likes] } ON COLUMNS,
{ TOPCOUNT([Products].[Name].Members, 10, [Measures].[Likes]) } ON ROWS
FROM [Likes]
WHERE ( [Date].[2014].[3].[29]:[Date].[2014].[4].[5] )
Here are the results:
[Measures].[Likes]
[Product].[XX]
[Product].[XX]
[Product].[XX] 139
[Product].[XX]
[Product].[XX] 1
[Product].[XX]
[Product].[XX]
[Product].[XX] 125
[Product].[XX] 111
[Product].[XX] 1
If I change the top limit to 20, for example, the results will have more products with likes but also with more empty ones, and not ordered (like a top usually is).
Using NON EMPTY makes the query return only 5 results instead of 10, and still not ordered.
Thanks!
Try this query
SELECT
{ [Measures].[Likes] } ON 0,
Head(ORDER([Products].[Name].Members,[Measures].[Likes], DESC), 10) ON 1
FROM [Likes]
WHERE ( [Date].[2014].[3].[29]:[Date].[2014].[4].[5] )

SQL Ranking Statement for Access- Duplicates in Results

I have a simple Access table [Parts] that stores the data
Part# CYTD_SALES CUST_NUM
I need to rank the parts in terms of CYTD Sales (Current Year To Day Sales) for each CUST_NUM (Customer Number) separately
I am using the following statement:
Rank:
(SELECT Count (*)
FROM [Parts] as R
Where [CYTD Sales] > [Parts].[CYTD Sales]
And > CUST_NUM= [Parts].[CUST_NUM] ) + 1
I ran into situation when the same amount was spent for more than 1 part by same customer, so the ranking looks like this
1 2 4 4 5
instead of
1 2 3 4 5
Is there a way to write a statement that would not allow identical rankings for the same customer?
Thank you!
Since Part# field is unique for each customer, below is the statement that worked for me:
(SELECT Count (*)
FROM [Parts] as R
Where ([CYTD Sales] > [Parts].[CYTD Sales] Or
([CYTD Sales]=[Parts].[CYTD Sales] And
[Part#]> [Parts].[Part#]))
And > CUST_NUM= [Parts].[CUST_NUM] ) + 1