Query to only display matching elements in two dimensions - mdx

Short question:
Any idea how I can pull the name from one dimension entry and apply it to another as filter?
Long description: My cube has has dimensions for manufacturer and seller, and I only need sales for "themselves". The dimensions are loaded from distinct tables in the source but have entries with the exact same name.
Manufacturer Seller
A A *
A D
B B *
C C *
C A
C D
A, B and C sell their products themselves, A and C also sell through reseller D. C also sells through A. I'd like to filter for the marked rows only (names matching).
In SQL this would be simple, or the cube might be easily enhanced to flag "own sales", but both options are not available. I need to query the cube "as is".
I tried using STRTOMEMBER and CURRENTMEMBER like so (with NAME and MEMBER_NAME):
STRTOMEMBER("[Dim Seller].[Seller].[" + [Dim Producer].[Producer].CURRENTMEMBER.NAME + "]
That actually works, syntactically, but CURRENTMEMBER seems to always evaluate to ALL and delivers the (correct) measure value for the ALL element yet not the one for matching name.
I also tried to create a WHERE setting the two names equal
[Dim Seller].[Seller].CURRENTMEMBER.NAME = [Dim Producer].[Producer].CURRENTMEMBER.NAME
but that is very SQL and not valid in MDX.
The whole query looks like this:
SELECT
NON EMPTY {
[Measures].[Value]
} ON COLUMNS
, NON EMPTY { (
{
[Dim Producer].[Producer].[A]
, [Dim Producer].[Producer].[B]
, [Dim Producer].[Producer].[C]
}
* [Dim Seller].[Seller].[Seller].ALLMEMBERS
// This line needs to be trimmed to same name as producer
) } ON ROWS
FROM
[Cube]
The producer list is coming from a config file and string-concatenated to the query and subject to change. Having a second seller list to be kept in sync would be a burden but also (when C sells through A) deliver wrong results.
Any idea how I can pull the name from one dimension entry and apply it to another?

The HAVING clause might help you:
SELECT
NON EMPTY {
[Measures].[Value]
} ON COLUMNS
, NON EMPTY {
{
[Dim Producer].[Producer].[A]
, [Dim Producer].[Producer].[B]
, [Dim Producer].[Producer].[C]
}
* [Dim Seller].[Seller].[Seller].ALLMEMBERS
}
HAVING
[Dim Seller].[Seller].CURRENTMEMBER.MEMBER_NAME =
[Dim Producer].[Producer].CURRENTMEMBER.MEMBER_NAME
ON ROWS
FROM
[Cube]

Use the GENERATE function to do the job for you.
with set Producers as
{[Dim Producer].[Producer].[A]
,[Dim Producer].[Producer].[B]
,[Dim Producer].[Producer].[C]}
set Sellers as
[Dim Seller].[Seller].members
//For every producer, get the seller who shares the same name.
set ProducersHavingSameNameAsSellers as
GENERATE(Producers, GENERATE(Sellers, filter
(Sellers,
[Dim Seller].[Seller].CURRENTMEMBER.MEMBER_NAME =
[Dim Producer].[Producer].CURRENTMEMBER.MEMBER_NAME
)
)
)
SELECT
NON EMPTY [Measures].[Value] ON COLUMNS,
ProducersHavingSameNameAsSellers ON ROWS
FROM [Cube]

Related

Number or Results and WITH MEMBER Calculation interacting weird

In our MDX Queries, we use a template like the following WITH MEMBER . SELECT SUBSET . FROM (SELECT . FROM .) a lot.
What this particular query should do (and does!) is list all product variants matching a filter, and give the sales amount for it for a month in time. On the same row, we have the sales total of all variants of this product.
We need only a subset of the result (for paging), and the results need to ordered to allow paging of course. Then there is a non empty, so only product variants that were sold in the time period qualify.
This works just fine. Paging also works: putting 30, 60, 90 for Start in SUBSET is gives the correct results.
However, if I put a 1 as Count (SUBSET(..., x, 1)) the result of the "Price all" goes to (null) for each and any row I select with x. If I return two or more rows it works just fine, and all rows have their correct values.
Two results and the correct value in the rightmost column (in case you are wondering how the total of all variants, 67, can be lower than the sales of one particular variant (280): I picked a bad example - there was a return (so a negative sale) for another variant of this product, for 213. The 67 is correct and desired!)
One Row and a (null) result
I do not understand how or why the SUBSET count would interfere with the Tuple I select in the WITH MEMBER. If it does it for 30 rows at a time, why not for one?
*edit
I just tried, what would happen if I filter in a way that only one result matches (and SUBSET paging is set to "working values" of 0, 30): The same as in the 2nd screenshot, for one result row the WITH MEMBER evaluates to (null).
So it is not that SUBSET is the problem, but more general: When there is only one result row!
Could this be a bug in our SQL Server Version? It is SQL 2012 with SP4 and all latest security patches.
WITH
MEMBER [DIM Date].[HI Year_Month_Day].[CURRENT_MONTH] AS
[DIM Date].[HI Year_Month_Day].&[20201215].Parent /* Select Month of December */
MEMBER [MEASURES].[Price all] AS (
(
[DIM Products].[HI Products].Currentmember.Parent
, [DIM Products].[HI Subproduct].[Total]
)
, [MEASURES].[Price]
), FORMAT_STRING = '#,0' /* Get the parent product total next to every subproduct */
SELECT {
([DIM Datum].[HI Year_Month_Day].[CURRENT_MONTH], [MEASURES].[Price])
, ([DIM Datum].[HI Year_Month_Day].[CURRENT_MONTH], [MEASURES].[Price All])
} ON COLUMNS
, {
SUBSET(
ORDER(
NONEMPTY(
([DIM Products].[HI Produt Subproduct].[Subproduct])
, {([DIM Date].[HI Year_Month_Day].[CURRENT_MONTH], [MEASURES].[Price])}
)
, ([DIM Date].[HI Year_Month_Day].[CURRENT_MONTH], [MEASURES].[Price])
, BDESC
)
, 0
, 30
)
} ON ROWS
FROM (
SELECT
{[DIM StoreLocation].[HI Country].[Country].&[US]}
* {[DIM Productgroup].[HI Productgroup].[Productgroup].&[Bikes]}
ON COLUMNS
FROM [Cube]
)

MDX - Grand total missing when filtering

I've been working on an ExcelDNA C# xll that allows users to enter simple words (under guidance) and I construct the elaborate MDX for them to query against a remote ActivePivot cube.
During testing I've ntoticed that when filtering, the grand total disappears (presumably it's joining tuples together). How do I still get a grand total? Do I need to use SCOPE or create a calculated member?
Thanks to more advanced MDX people:
SELECT
NON EMPTY
{
[Measures].[Notional.SUM]
,[Measures].[Notional.SHORT]
,[Measures].[Notional.LONG]
} ON COLUMNS
,NON EMPTY
Hierarchize
(
Filter
(
(
[CDR].[CDR].MEMBERS
,[Book].[Book].MEMBERS
)
,
Left([Book].[Book].CurrentMember.MemberValue,2) = "22"
)
,POST
) ON ROWS
FROM [TraderCube]
WHERE
[Date].[Date].[2020-01-24];
The following is something similar against AdvWrks cube:
WITH
//>>inside the WITH clause we have moved the set
SET [FilteredSet] AS
{
Filter
(
[Reseller].[Reseller Type].[Business Type].MEMBERS
,
Left([Reseller].[Reseller Type].CurrentMember.MemberValue,2) = "sp"
OR
Left([Reseller].[Reseller Type].CurrentMember.MemberValue,2) = "VA"
)
}
//>>next we create a custom member that is the sum of the filtered set
MEMBER [Reseller].[Reseller Type].[All Visible Resellers] AS
Aggregate([FilteredSet])
SELECT
NON EMPTY
{[Measures].[Reseller Sales Amount]} ON COLUMNS
,NON EMPTY
//>> inside these curly brackets we declare a set that is the filtered set and the Total member
{
[FilteredSet]
,[Reseller].[Reseller Type].[All Visible Resellers]
} ON ROWS
FROM [Adventure Works]
WHERE
[Date].[Calendar].[Calendar Year].&[2013];
The results of the above is the following:

Simple Calculated Member Running for Forever - MDX

I am facing very strange issue with MDX (SSAS 2014), on which simplest calculated member is taking forever to execute. Could someone please help me to understand why i am facing this issue. If i not use calculated member everything works fast and result comes in seconds. When i remove Producer attribute, query performances well.
Below is the complete query.
WITH
MEMBER Measures.AsOfDate AS ("[Policy Effective Date].[Year-Month].[Date].&[2018-01-04T00:00:00]")
MEMBER Measures.YTDPremium AS AGGREGATE (YTD(STRTOMEMBER(Measures.AsOfDate)), [Measures].[Written Premium])
SELECT NON EMPTY
{
Measures.YTDPremium
} ON COLUMNS, NON EMPTY
{
(
[Program].[Program Name].[Program Name]
,[Insuring Company].[Insuring Company Name].[Insuring Company Name]
,[Line Of Business].[Line Of Business].[Line Of Business]
,[Producer].[Producer Name].[Producer Name]
)
} ON ROWS
FROM [Premium]
Try understand what the following part does in your query
NON EMPTY { ( [Program].[Program Name].[Program Name]
,[Insuring Company].[Insuring Company Name].[Insuring Company Name]
,[Line Of Business].[Line Of Business].[Line Of Business]
,[Producer].[Producer Name].[Producer Name]
) } ON ROWS
In the above MDX you are telling the server to take a cross product of all values of "Programs", "Line Of Business" and "Producer Name". So lets say you have 4 values of programs , 3 values of line of business and 2 values of producer name. The total combinations are 4*3*2=24
Now the "Non empty" removes any combinations that are not present in your dataset. This is done by removing all rows that have "Null" value in column value.
Your measure is returning value irrespective if that combination exists or not. You can modify your Calculatedmeasure to return value only in the case if the combination is valid. This can be achived by checking an actual measure for that combination
Edit: based the below example is based on the comment
In the below example i am trying to get the internet sales amount categories and components
select
{ [Measures].[Internet Sales Amount] }
on columns,
(
[Product].[Category].[Category],
[Customer].[Country].[Country]
)
on rows
from [Adventure Works]
Result
Now add "Non empty" to the query and observe the results.
Results
Now lets add calculted measure that returns "hello". Notice how the non empty clause is ineffective.
Now modify the code make the calculated measure check other measures for null
with member measures.t as
case when [Measures].[Internet Sales Amount] = null then null else "hello" end
select
{ [Measures].[Internet Sales Amount] ,measures.t }
on columns,
non empty
(
[Product].[Category].[Category],
[Customer].[Country].[Country]
)
on rows
from [Adventure Works]
Result
The bottom line: Because of cross product your result is so huge that SSAS is having hard time handling it.

MDX subtract measures across dimensions

WITH
MEMBER CostDifference AS
Sum([Measures].[ExtendedCost]) - [Measures].[ExtendedCost]
SELECT
NON EMPTY
{
[Measures].[ExtendedCost]
,CostDifference
} ON COLUMNS
,NON EMPTY
{[Parts].[ItemDesc].MEMBERS, [Dim Date].[DateUK].MEMBERS} ON ROWS
FROM [Cube]
I'm trying to subtract a measures across different dimensions i.e. for 2 date snapshots (31/1/2010 and 28/2/2010) for all the products in DimParts
if I remove this piece of code from equation then all I get is zeros
[Dim Date].[DateUK].MEMBERS
If I use a cross join to add more than one dim even then the cost difference is zero
e.g. ,NON EMPTY
CrossJoin
(
[Parts].[ItemDesc].MEMBERS
,{[Dim Date].[DateUK]}
) ON ROWS
I'm using SQl Server 2008R2
What am I missing here.
This Sum([Measures].[ExtendedCost]) - [Measures].[ExtendedCost]
Will resolve to this
[Measures].[ExtendedCost] - [Measures].[ExtendedCost]
Which is always 0
If this Sum([Measures].[ExtendedCost]) needs to be across a complete set then you need to include that set:
Sum(
[Dim Date].[DateUK].MEMBERS
,[Measures].[ExtendedCost]
)

How to indicate the measure when use dimension members as ROWS in mdx query?

Here is the query that I am using:
SELECT
NON EMPTY { [Dim Date].[Week].[Week].Members } ON COLUMNS,
[Dim Source].[Source Name].[Source Name].Members ON ROWS
FROM [Some Cube];
The things is, right now, I have many measures.
But as I am using dimension members on COLUMNS, I cannot indicate the measure anymore.
So this query results in a default measure.
My question is how can I indicate the measure instead of using the default in mdx query?
Or is there any other way that I can do this query (dimension in both row and columns is required for reading result logic in C# in possible) ?
You can do it in two ways:
Either on the SELECT statement, as
{ [Dim Date].[Week].[Week].Members } * { [Measures].[My Measure] } ON COLUMNS,
or on the WHERE slicer by adding
WHERE [Measures].[My Measure]
at the end.