I am new to MDX and wondered if it is possible to create a query that shows a Sales amount per Year and per Month on two different axes, even if the sales date is a single dimension.
Something like:
Sales | 2010 | 2011 | Diff
---------+-----------+------------+----------
Jan | 1234,00 | 2345,10 | +80%
Feb | ...
...
EDIT: Added mondrian to tags, because there seem to be possibilities with other MDX implementations not available in mondrian.
Yes the solution is around calculated members :
Let's imagine your initial MDX looks like :
Select
{ [Calendar].[Year].[2010],[Calendar].[Year].[2011] } on 0,
{ [Calendar].[Months].members } on 1
from [Cube]
You can add a calculated member in the [Year] hierarchy :
With
Member [Calendar].[Year].[Diff] as [Calendar].[Year].[2011] / [Calendar].[Year].[2010]-1, FORMAT_STRING='percent'
Select
{ [Calendar].[Year].[2010],[Calendar].[Year].[2011], [Calendar].[Year].[Diff] } on 0,
{ [Calendar].[Months].members } on 1
from [Cube]
You can also add a more elegant and flexible solution, by using utility or statistical dimensions. Those dimension instead of holding data define transformations / functions and the output will not be exactly the one you're looking, but it's an interesting concept.
The problem can be solved with the ParallelPeriod function:
WITH MEMBER [Measures].[Einheiten Vorjahr]
AS '(ParallelPeriod([Year],1),
[Measures].[quantity])'
SELECT {[Measures].[quantity],[Measures].[Einheiten Vorjahr]} ON COLUMNS,
[date].[2010].children on rows
FROM salesorderitems
Related
There are three queries A, B and C. I should compare the queries B and C to query A. And answer if in comparison to A: are the results of B and C respectively to a rollup, drill down or nothing of these.
Query A:
SELECT
Geography.Region, Time.Month, SUM (Sales.numberSold)
FROM
Sales, Time, Product, Geography
WHERE
Sales.ProductID = Product.ProductID
AND Sales.TimeID = Time.TimeID
AND Sales.GeoID = Geography.GeoID
AND Product.ProductFamily = "video"
AND Time.Year = 2000
AND Geography.Country = "Germany"
GROUP BY
Geography.Region, Time.Month;
Query B:
SELECT
Geography.Region, Time.Month, SUM (Sales.numberSold)
FROM
Sales, Time, Geography
WHERE
Sales.TimeID = Time.TimeID
AND Sales.GeoID = Geography.GeoID
AND Time.Year = 2000
AND Geography.Country = "Germany"
GROUP BY
Geography.Region, Time.Month;
Query C:
SELECT
Geography.City, Time.Month, SUM (Sales.numberSold)
FROM
Sales, Time, Product, Geography
WHERE
Sales.ProductID = Product.ProductID
AND Sales.TimeID = Time.TimeID
AND Sales.GeoID = Geography.GeoID
AND Product.ProductFamily = "video"
AND Time.Year = 2000
AND Geography.Country = "Germany"
GROUP BY
Geography.City, Time.Month;
Compare the queries B and C to query A.
In comparison to A: are the results of B and C respectively:
a rollup or
a drill down or
neither of these two?
The gaps are
The result of query ...... is .......................... in comparison to the result of query A".
The missing parts to be inserted are: "B", "C" and "a rollup", "a drill down", or "neither"
My words
The result of query B is a rollup in comparison to the result of query A".
I don't know if my answer is correct. What is the solution here for this point and why ?
Cube:
A cube consists of cells each of which is defined by the intersection
of all dimensions (axes) belonging to this cube. Each cell of the cube
can contain one or more measures.
Rollup:
The CUBE operator calculates aggregations by combining all possible
subsets of the attributes listed in the parentheses following the word
CUBE. Often, not all the combinations are necessary, however, but it
may be sufficient to aggregate only by taking first one attribute,
then two, then three, etc. until all are taken together. This is done
by the ROLLUP operator.
Drill Down:
In contrast to simple data access, OLAP requires a multidimensional
data model that is built according to analysis needs. => Not a
relational technique. OLAP allows data analysis with the goal of
discovering new information. Reports present consolidated values in
tables and images. The functionality allows for instance to "drill
down" to detailed data and "drill up" ("roll up") again.
Drill down and roll up functions are inverse and allow you to add and remove granularity in axes like a zoom.
a roll up - less granularity in the target table (for example years instead of months)
a drill down - more granularity in the target table (months instead of years)
neither of these two - there is other data in the tables
A three-dimensional cube is given, where the dimensions are:
Geography
Time
Product
Values are sales volumes (SUM (Sales.numberSold)).
Let's call this source cube Z.
In the end, A, B, and C show only two dimensions:
Geography
Time
The Product is always shrunk into one dimension.
Cube A:
The Product is shrunk into one dimension by the slice for Product.ProductFamily = "video"
Z
rollup on Product (from ArticleName to ProductFamily)
slice for Product.ProductFamily = "video"
rollup on Time (from Day to Year)
slice for Time.Year = 2000
rollup on Geography (from BranchName to Country)
slice for Geography.Country = "Germany"
drill down Geography from Country to Region
drill down Time from Year to Month
A
Cube B:
The Product is shrunk into one dimension by rollup on Product (from ArticleName to All).
The B is formed from the Z with the same granularity of rollups and drills down.
The result of query B is neither of these two in comparison to the result of query A.
Z
rollup on Product (from ArticleName to All)
rollup on Time (from Day to Year)
slice for Time.Year = 2000
rollup on Geography (from BranchName to Country)
slice for Geography.Country = "Germany"
drill down Geography from Country to Region
drill down Time from Year to Month
B
Cube C:
The Product is shrunk into one dimension the same way as in Cube A.
So the only difference is in granularity.
The C is more detailed.
The result of query C is a drill down in comparison to the result of query A.
A
drill down Geography (from Region to City)
C
Sources:
Data Warehousing - OLAP on tutorialspoint
Online analytical processing on wikipedia
OLAP Operations in the Multidimensional Data Model on javatpoint
Z
. . . . .
. . . . .
+---+---+---+---+ .
audio 123 / 2 / 9 / / /|.
+---+---+---+---+ + .
video 321 / 3 / 6 / / /|/|.
+---+---+---+---+ + + .
video 123 / 5 / 2 / / /|/|/|.
+---+---+---+---+ + + + .
LA | 5 | 2 | | |/|/|/|.
+---+---+---+---+ + + +
NY | 3 | 8 | | |/|/|/:
+---+---+---+---+ + + :
| | | | |/|/:
+---+---+---+---+ + :
| | | | |/:
+---+---+---+---+ :
: : : : :
: : : : :
01-01-22
02-01-22
Edit 1:
The disadvantage of the sources is that they say what a given function is and not what it isn't. It is important to thoroughly understand what they do to determine what they can't.
Even if you only have to decide between the Roll-Up and the Drill Down it is necessary to understand the Slice in your example. The Slice is pretty weak, so it's a good idea to find out that it's a case of the Dice.
The Roll-Up and the Drill Down aggregate all values - the Group by clause.
The Slice (Dice) filters - the Where clause.
Things achieved by the Slice can't be achieved by the Roll-Up.
The Roll-Up and the Drill Down in dimension Product can scale on All (remove the dimension), Category, Family, Group, and Name.
In select A, we get rid of the Product dimension using the Slice and in query B using the Roll-Up to All.
The Slice in query A leaves only Sales.numberSold for "video". This can't be achieved with Roll up.
I want to define a cube measure in a SSAS Analysis Services Cube (multidimensional model) that calculates ratios for the selection a user makes for a predefined hierarchy. The following example illustrates the desired behavior:
|-City----|---|
| Hamburg | 2 |
| Berlin | 1 |
| Munich | 3 |
This is my base table. What I want to achieve is a cube measure that calculates ratios based on a users' selection. E.g. when the user queries Hamburg (2) and Berlin (1) the measure should return the values 67% (for Hamburg) and 33% (for Berlin). However if Munich (3) is added to the same query, the return values would be 33% (Hamburg), 17% (Berlin) and 50% (Munich). The sum of the values should always equal to 100% no matter how many hierarchy members have been included into the MDX query.
So far I came up with different measures, but they all seem to suffer from the same problem that is it seems impossible to access the context of the whole MDX query from within a cell.
My first approach to this was the following measure:
[Measures].[Ratio] AS SUM([City].MEMBERS,[Measures].[Amount])/[Measures].[Amount]
This however sums up the amount of all cities regardless of the users selection and though always returns the ratio of a city with regards to the whole city hierarchy.
I also tried to restrict the members to the query context by adding the EXISTING keyword.
[Measures].[Ratio] AS SUM(EXISTING [City].MEMBERS,[Measures].[Amount])/[Measures].[Amount]
But this seems to restrict the context to the cell which means that I get 100% as a result for each cell (because EXISTING [City].MEMBERS is now restricted to a cell it only returns the city of the current cell).
I also googled to find out whether it is possible to add a column or row with totals but that also seems not possible within MDX.
The closest I got was with the following measure:
[Measures].[Ratio] AS SUM(Axis(1),[Measures].[Amount])/[Measures].[Amount]
Along with this MDX query
SELECT {[Measures].[Ratio]} ON 0, {[City].[Hamburg],[City].[Berlin]} ON 1 FROM [Cube]
it would yield the correct result. However, this requires the user to put the correct hierarchy for this specific measure onto a specific axis - very error prone, very unintuitive, I don't want to go this way.
Are there any other ideas or approaches that could help me to define this measure?
I would first define a set with the selected cities
[GeoSet] AS {[City].[Hamburg],[City].[Berlin]}
Then the Ratio
[Measures].[Ratio] AS [Measures].[Amount]/SUM([GeoSet],[Measures],[Amount])
To get the ratio of that city to the set of cities. Lastly
SELECT [Measures].[Ratio] ON COLUMNS,
[GeoSet] ON ROWS
FROM [Cube]
Whenever you select a list of cities, change the [GeoSet] to the list of cities, or other levels in the hierarchy, as long as you don't select 2 overlapping values ([City].[Hamburg] and [Region].[DE6], for example).
I have an MDX/calculated member question here. It has been a while since I've done this and have forgotten a lot. I have a cube with the following dimensions and levels:
Sites
Site Name
Clients
Client Name
Industry Name
I have a measure
Product Count
What I want to show/return from an MDX query is the following:
Site | Prod Count | Avg Prod Count Across All Sites for Current Client | Avg Prod Count
Across All Sites in Current Client's Industry
Example Data:
Site | Prod Count | Avg 1 | Avg 2
Site 1 | 100 | 50 | 200
Site 2 | 125 | 50 | 200
Site 3 | 112 | 50 | 200
What I'm trying to figure out is how or if I can use 2 different calculated members to calculate the averages above.
The challenge is that the query has to be in the following format because I'm using a reporting tool and it is generating the MDX.
`SELECT
{
[Measures].[Product Count],
[Measures].[Calc Avg 1],
[Measures].[Calc Avg 2]
} ON COLUMNS,
{[Sites].[Site Name].[Site Name].Members} ON ROWS
FROM [Cube]
where ([Clients].[Client Name].&[Client A])`
So basically, my question is:
What would be the proper way to define the averages I'm looking for using calculated members?
Whenever I try it out I'm only able to calculate the average product count across all sites for the current client, but I'm not able to get the average across all sites in the current client's industry.
here's an example using adventure works to get you started. the calculated members will need to be ported to the MDX script to use with your tool. Here's the mapping:
City = "Client Site"
State = "Client"
Country = "Client Industry"
WITH
MEMBER Measures.ClientCitiesCount AS
Exists(
[Customer].[City].[City] // represents client sites
,[Customer].[State-Province].CurrentMember // represents client
).Count
MEMBER Measures.ClientCitiesSales AS
SUM(
[Customer].[State-Province].CurrentMember
,[Measures].[Internet Sales Amount]
)
MEMBER Measures.AvgAcrossClientCities AS
ClientCitiesSales/ClientCitiesCount
MEMBER Measures.IndustryCitiesCount AS
Exists(
[Customer].[City].[City] // represents industry sites
,Exists(
[Customer].[Country].[Country] // represents client's industry
,[Customer].[State-Province].CurrentMember // represents client
)
).Count
MEMBER Measures.IndustryCitiesSales AS
SUM(
Exists(
[Customer].[Country].[Country]
,[Customer].[State-Province].CurrentMember
)
,[Measures].[Internet Sales Amount]
)
MEMBER Measures.AvgAcrossIndustryCities AS
IndustryCitiesSales/IndustryCitiesCount
SELECT
{
[Measures].[Internet Sales Amount]
,ClientCitiesCount
,ClientCitiesSales
,AvgAcrossClientCities
,IndustryCitiesCount
,IndustryCitiesSales
,AvgAcrossIndustryCities
} ON 0,
{
[Customer].[City].[City] // represents client sites
} ON 1
FROM
[Adventure Works]
WHERE
[Customer].[State-Province].&[GA]&[US] // represents client
Don't forget to add in some edge-case handling (e.g. IIF the client has 0 "sites" in context) and consider using the "measuregroup" parameter in the EXISTS function.
I am new to MDX and I just want to ask if it is possible in MDX query to make aggregations and groupings on the fly.
Here is the scenario, I have a dimension called "Department". And it has department code values e.g.
1234
1257
1346
1390
I also had a measure called "Sales".
What I need to do here is to make a Calculated Member that will get the Maximum "Sales" grouped per department based on the its first two digits. For example, consider the following output when browsing the cube using the Department dimension and Sales Measure
Department | Sales
1234 | 100
1257 | 200
1346 | 100
1390 | 400
Then I need to make an MDX query to produce an output something like below,
Department | Sales
12xx | 200
13xx | 400
You will notice that Maximum Sales based on the two digits of each department concatenated with "xx" string were the expected output.
Well determining the maximum is not a problem. with <name> as max(<something>) but you should reconsider the approach with the on the fly grouping.
I'm sure, that it is achievable, although I cannot provide a solution, but it will perform poorly. (I'm assuming that the digits of the department are not implemented as measure)
If you need this grouping more often you should add an additional dimension, or better a hierarchy to the department dimension.
I have the following star schema:
Objects <-> Facts <-> Simulation
-ObjectID -ObjectID -SimulationID
-SimulationID -SimulationID
-ObjHierarchy -Volume
-ObjectType
Now I'm trying to filter the cube using both dimensions:
select [Measures].[Volume] on columns,
[Objects].[ObjHierarchy].[Level 02] on rows
from [DM OC]
where ([Objects].[ObjectType].&[2], [Simulation].[SimulationID].&[52])
However, this returns rows for SimulationID=52 (with values) but also duplicates for SimulationID=53 (with nulls):
ObjHierarchy | Volume
MyObj1 | 12345
MyObj2 | 54321
MyObj1 | (NULL)
MyObj2 | (NULL)
A workaround is to use NonEmpty, however it just seems the cube isn't modeled the right way.
It is a usual case and doesn't mean that the cube's model wrong.
In MDX, you should also filter the rows by using any filter function if you don't want them to appear in your result. In your case, you should use NonEmtpy to eleminate the empty values.
Can you execute the following :
with member XX as [Objects].[ObjHierarchy].currentMember.Properties( "KEY" )
select { [Measures].[Volume], XX } on columns,
[Objects].[ObjHierarchy].[Level 02] on rows
from [DM OC]
where ([Objects].[ObjectType].&[2], [Simulation].[SimulationID].&[52])
MyObj1 and MyObj2 should not have the same key; otherwise I do not see right now.