OUTPUT
Negative Total Actual Total
Marketing (Expense) Advertising December Barlens Actual 24010.44 24,010.44
Marketing (Income) Discounts December Barlens Actual 43380.4 -43,380.40
Marketing (Income) Sale Promot December Barlens Actual 18.91 18.91
Marketing (Income) Sale Sponso December Barlens Actual 9181.32 -9,181.32
Marketing (Expense) TOTAL December Barlens Actual 24010.44 24,010.44
Marketing (Income) TOTAL December Barlens Actual 52542.81 -52,542.81
/* Here Marketing (Income) is being converted into + value (ie -43,380.40, -9,181.32 converted to 43380.4,9181.32) but the 18.91 value is + income so i dont want to display it. Again, The two totals Marketing(Expense) and Marketing (income) are displaying separately but i want to display them in a line so the Total should be 24010.44+ 43380.4 + 9181.32= 76572.16 */
WITH
MEMBER [Measures].[Negative Total] AS
CASE
WHEN ([Measures].[Total]) < 0 THEN [Measures].[Total]* -1 /* Actullay i want to display those marketing income has - value so condition should be like this WHEN ([Dim Account].[HierarchyMarketing].[Account Marketing].&[Income]&[Marketing],[Measures].[Total]) < 0 */
THEN [Measures].[Total]* -1
ELSE [Measures].[Total]
END
MEMBER
[Dim Account].[Account Activity].TOTAL AS
[Dim Account].[Account Activity].[All]
SELECT
NON EMPTY
{[Measures].[Negative Total],[Measures].[Total]}
ON COLUMNS
,
NON EMPTY
(
{
{
[Dim Account].[HierarchyMarketing].[Account Marketing].&[Expenses]&[Marketing]
,
[Dim Account].[HierarchyMarketing].[Account Marketing].&[Income]&[Marketing]
}
*
[Dim Account].[Account Activity].[Account Activity].MEMBERS
,
{
[Dim Account].[HierarchyMarketing].[Account Marketing].&[Expenses]&[Marketing]
,
[Dim Account].[HierarchyMarketing].[Account Marketing].&[Income]&[Marketing]
}
*
[Dim Account].[Account Activity].TOTAL
}
,[Dim Fiscal Year].[HierarchyFiscal].[E Month].&[2016]&[December]
, [Dim Branch].[Trading As].&[BAR]&[Barlens Event Hire]
, NONEMPTY([Dim Scenario].[Scenario Name].&[Actual])
)
ON ROWS
FROM [CubeProfitLoss]
I have a problem with data displaying and calculation matter. The following MDX displays all the positive total (MEASURES.Total) and if any negative total then converted them into + value and are displayed accordingly. However, my requirement is in Hierarchy Marketing i have Expense and Income, i want to display all expenses and those income have negative value and exclude positive income from calculation. So the TOTAL value will be all expenses+ (-) income per Traders. But currently it is being calculated as separately i mean, for example trader (barlens) shows 2 total 1 for expense and another for income of marketing.
could you please find that solution ? I would be really appreciate your help, because last 2 weeks i have been trying to sort out this problem.
You can use the HAVING clause
I am a little surprised that your code runs - it is a little strange seeing currentmember used the way you have used it - does it serve a purpose or does the following give you the same results:
Maybe the additional NONEMPTY is also redundant in the way you have used it? You could maybe simplify all of the ON ROWS section to the following:
WITH
MEMBER [Measures].[Negative Total] AS
CASE
WHEN (SUM([Dim Account].[Account Marketing].&[Income]&[Marketing],[Measures].[Total])) < 0 THEN [Measures].[Total]* -1
WHEN (SUM([Dim Account].[Account Marketing].&[Income]&[Marketing],[Measures].[Total]))> 0 THEN 0
ELSE [Measures].[Total]
END
,SOLVE_ORDER = 2
MEMBER [Dim Account].[Account Marketing].[All].[Total Marketing Expense] AS
AGGREGATE(
{
[Dim Account].[Account Marketing].&[Expenses]&[Marketing]
,[Dim Account].[Account Marketing].&[Income]&[Marketing]
}
)
,SOLVE_ORDER = 1
MEMBER [Dim Account].[Account Activity].TOTAL AS
[Dim Account].[Account Activity].[All]
SELECT
NON EMPTY
{[Measures].[Negative Total],[Measures].[Total]} ON 0,
NON EMPTY
{
[Dim Account].[Account Marketing].&[Expenses]&[Marketing]
,[Dim Account].[Account Marketing].&[Income]&[Marketing]
,[Dim Account].[Account Marketing].[All].[Total Marketing Expense]
}
*[Dim Account].[Account Activity].[Account Activity].MEMBERS
*[Dim Fiscal Year].[HierarchyFiscal].[E Month].&[2016]&[December]
*[Dim Branch].[Trading As].&[BAR]&[Barlens Event Hire]
*[Dim Scenario].[Scenario Name].&[Actual]
//HAVING [Measures].[Negative Total] <> [Measures].[Total]
ON 1
FROM [CubeProfitLoss];
Related
I would like to query the total sales of each country with the GDP growth rate of more than 3. So far, I can display the sales information of each country like such:
SELECT
{[Measures].[Sales]} ON 0,
{[Dim Company Info].[LOC].ALLMEMBERS} ON 1
FROM [Database]
But then I am still blank on how to query all GDP growth rate of more than 3. I have searched SO and found filter to be the answer, however, I do not know where to include it in my code above. How do I go about this?
Edit: I have tried the followings, but I do not think that is what I am supposed to do:
WHERE ([Dim Company Info].[Gdp Growth].&[3] : [Dim Company Info].[Gdp Growth].&[3].LastChild)
and
SELECT
{[Measures].[SALES]} ON 0,
{FILTER([Dim Company Info].[LOC].MEMBERS, [Dim Company Info].[Gdp Growth] > 3)} ON 1
FROM [766 Database]
and
SELECT
{[Measures].[SALES]} ON COLUMNS,
{[Dim Company Info].[LOC].MEMBERS} ON ROWS
FROM [766 Database]
WHERE FILTER([Dim Company Info].[Gdp Growth], [Dim Company Info].[Gdp Growth] > 2)
You can use your below expression when the dimension members are numericly arranged
WHERE ([Dim Company Info].[Gdp Growth].&3 : [Dim Company Info].[Gdp
Growth].&3.LastChild)
with a slight correction
WHERE ([Dim Company Info].[Gdp Growth].&[3] : [Dim Company Info].[Gdp Growth].[Gdp Growth].LastChild)
However if that is not the case, then you need to follow the below method.
I am reporting the product with the max quantity.
select {[Measures].[Internet Sales Amount]} on 0,
non empty
([Product].[Product].[Product],[Promotion].[Max Quantity].[Max Quantity]) on 1
from [Adventure Works]
Now lets manipulate the max quantity to make it behave like a measure.
with
member measures.test
as
case when [Measures].[Internet Sales Amount]>0 then
(nonempty(([Product].[Product].currentmember,[Promotion].[Max Quantity].[Max Quantity]),[Measures].[Internet Sales Amount])).item(0).item(1).name
else
null end
select
{[Measures].[Internet Sales Amount],measures.test}
on 0,
non empty ([Product].[Product].[Product] )
on 1
from [Adventure Works]
Now you can use the filter, but we need to cast(note the use of CInt) the data too
with
member measures.test
as
case when [Measures].[Internet Sales Amount]>0 then
Cint((nonempty(([Product].[Product].currentmember,[Promotion].[Max Quantity].[Max Quantity]),[Measures].[Internet Sales Amount])).item(0).item(1).name)
else
null end
select
{[Measures].[Internet Sales Amount],measures.test}
on 0,
non empty (
filter(
[Product].[Product].[Product]
,measures.test>0)
)
on 1
from [Adventure Works]
I'm trying to write MDX query for pivot table.
Similar query in RDBMS is like this:
SELECT stats_Date
,ISNULL(SUM(clicks), 0) AS clicks
,ISNULL(SUM(CASE WHEN ad_type IN (1,3) THEN clicks END), 0) AS keyword_clicks
,ISNULL(SUM(CASE WHEN ad_type IN (2,3) THEN clicks END), 0) AS direct_clicks
FROM STATS_TABLE (NOLOCK)
WHERE stats_Date BETWEEN '2015-06-01' AND '2015-06-30'
GROUP BY stats_Date
I've two dimensions [DIM TIME] & [DIM AD TYPE]
I've tried below MDX query for this:
WITH
MEMBER [Measures].[Clicks Keyword] AS
IIF
(
[DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
,[Measures].[clicks]
,0
)
SELECT {
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
,{
[DIM TIME].[CalendarHierarchy].[Date]*[DIM AD TYPE].[Ad Type].[Ad Type]
} ON ROWS
FROM [CM_STATS_CUBE]
WHERE ([DIM TIME].[Month].&[201506]:[DIM TIME].[Month].&[201506]})
Sample output of this MDX query looks like this:
Clicks Clicks Keyword
20150501 Invalid (null) 0
20150501 unknown 200 0
20150501 Keyword 500 0
20150501 Ads 300 300
20150502 Invalid (null) 0
20150502 unknown 400 0
20150502 Keyword 600 0
20150502 Ads 500 500
but I want to only group by stats_date and the expected output is:
Clicks Clicks Keyword
20150501 1000 300
20150502 1500 500
Similar example for testing in [Adventure Works] cube database:
WITH
MEMBER [Measures].[Internet Sales Amount US] AS
IIF( [Customer].[Customer Geography].CurrentMember IS [Customer].[Customer Geography].[Country].&[United States]
,[Measures].[Internet Sales Amount]
,NULL
)
SELECT {
[Measures].[Internet Sales Amount]
,[Measures].[Internet Sales Amount US]
} ON 0
,NON EMPTY{[Date].[Calendar].[Date]} ON 1
FROM [Adventure Works]
WHERE {[Date].[Date].&[20050701]:[Date].[Date].&[20050702]}
You don't need to bother with the cross-join [DIM TIME].[CalendarHierarchy].[Date]*[DIM AD TYPE].[Ad Type].[Ad Type]
WITH
MEMBER [Measures].[Clicks Keyword] AS
IIF
(
[DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
,[Measures].[clicks]
,0
)
SELECT
{
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
,{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
FROM [CM_STATS_CUBE]
WHERE
[DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
Also I would suggest using null rather than 0 in your IIF function - this should tidy up the result and speed things up:
WITH
MEMBER [Measures].[Clicks Keyword] AS
IIF
(
[DIM AD TYPE].[Ad Type].CurrentMember IS [DIM AD TYPE].[Ad Type].&[1]
,[Measures].[clicks]
,null //<<<<<<<<<<<<<<<<< better to use null rather than 0
)
SELECT
{
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
, NON EMPTY //<<<<<<<<<<<<<<<<< now if Clicks and Clicks Keyword are both null the respective row will be excluded
{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
FROM [CM_STATS_CUBE]
WHERE
[DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
Edit
I'd not read your script in enough detail - apologies. You can just just aggregate a set of two tuples:
WITH
MEMBER [Measures].[Clicks Keyword] AS
Sum
(
{
([DIM AD TYPE].[Ad Type].&[1],[Measures].[clicks])
,([DIM AD TYPE].[Ad Type].&[3],[Measures].[clicks])
}
)
SELECT
{
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
, NON EMPTY //<<<<<<<<<<<<<<<<< now if Clicks and Clicks Keyword are both null the respective row will be excluded
{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
FROM [CM_STATS_CUBE]
WHERE
[DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506];
The AdvWrks example you posted would just be a single tuple:
WITH
MEMBER [Measures].[Internet Sales Amount US] AS
(
[Customer].[Customer Geography].[Country].&[United States]
,[Measures].[Internet Sales Amount]
)
SELECT {
[Measures].[Internet Sales Amount]
,[Measures].[Internet Sales Amount US]
} ON 0
,NON EMPTY{[Date].[Calendar].[Date]} ON 1
FROM [Adventure Works]
WHERE {[Date].[Date].&[20050701]:[Date].[Date].&[20050702]}
If you wanted to add in Canada then there seem to be three viable alternatives:
1.
WITH
MEMBER [Measures].[Internet Sales Amount US & Canada] AS
(
[Customer].[Customer Geography].[Country].&[United States]
,[Measures].[Internet Sales Amount]
)
+
(
[Customer].[Customer Geography].[Country].&[Canada]
,[Measures].[Internet Sales Amount]
)
2.
WITH
MEMBER [Measures].[Internet Sales Amount US & Canada] AS
Aggregate
(
{
[Customer].[Customer Geography].[Country].&[United States]
,[Customer].[Customer Geography].[Country].&[Canada]
}
,[Measures].[Internet Sales Amount]
)
3.
(Switch to Sum)
WITH
MEMBER [Measures].[Internet Sales Amount US & Canada] AS
Sum
(
{
(
[Customer].[Customer Geography].[Country].&[Canada]
,[Measures].[Internet Sales Amount]
)
,(
[Customer].[Customer Geography].[Country].&[United States]
,[Measures].[Internet Sales Amount]
)
}
)
Try this:
WITH
MEMBER [Measures].[Clicks Keyword] AS
AGGREGATE({[DIM AD TYPE].[Ad Type].&[1], [DIM AD TYPE].[Ad Type].&[3]}, [Measures].[Clicks])
SELECT NON EMPTY
{
[Measures].[Clicks]
,[Measures].[Clicks Keyword]
} ON COLUMNS
, NON EMPTY
{[DIM TIME].[CalendarHierarchy].[Date]} ON ROWS
FROM [CM_STATS_CUBE]
WHERE
([DIM TIME].[Month].&[201506] : [DIM TIME].[Month].&[201506]);
I am quite new to MDX and I need some help with this query.
Generate(
filter(
[Dim Products].[Product].[Product].members
*
[Dim Date].week.week.members,
[Measures].[Price]
),
nonempty(
topcount(
[Dim Price].[Price].[Price]
*
[Dim Products].[Product].currentmember
*
[Dim Date].week.currentmember,
1,
[Measures].[Price Count]
)
)
)
I am using the above Named Set in a dashboard tool (Dundas Dashboard) in order to retrieve the MODE (price value that repeats the most). It does show correct results however it is slow. It takes 2-3 seconds if there is a filter on a single week and takes about 6-7 seconds if there is no filter on week (shows data for all weeks). And this is in SSMS but the client tool takes even longer to get the result set, sometimes timing out.
After some tests it appears that the number of the rows in the fact table does not affect the performance, I've drastically decreased it but still the same. The performance increased, however, once I've decreased the number of members in 2 of the dimension tables - [Dim Price], [Dim Products]. Initially it was taking 20+ seconds to get result set but improved to 6-7 seconds once I've decreased the number of members as follows:
Table | Rows Before | Rows After
[Dim Price] | 2400 | 620
[Dim Products] | 1080 | 101
This makes me think there is a Cartesian Product between the 3 dimensions that is affecting the performance.
I need someone to advise how I can improve the query to increase the performance.
Try the EXISTING function before the NONEMPTY function like this:
Generate(
filter(
[Dim Products].[Product].[Product].members
*
[Dim Date].week.week.members,
[Measures].[Price] //<<<<<<<<<<SHOULD THIS NOT INCLUDE A CONDITION e.g. [Measures].[Price] > 0 ?
),
EXISTING nonempty(
topcount(
[Dim Price].[Price].[Price]
*
[Dim Products].[Product].currentmember
*
[Dim Date].week.currentmember,
1,
[Measures].[Price Count]
)
)
)
Attempt 2:
Generate(
filter(
NONEMPTY(
[Dim Products].[Product].[Product].members
*
[Dim Date].week.week.members,
[Measures].[Price]
)
),
EXISTING nonempty(
topcount(
[Dim Price].[Price].[Price]
*
[Dim Products].[Product].currentmember
*
[Dim Date].week.currentmember,
1,
[Measures].[Price Count]
)
)
)
Attempt 3:
GENERATE(
FILTER(
NONEMPTY(
[Dim Products].[Product].[Product].MEMBERS
*
[Dim Date].week.week.MEMBERS
),
[Measures].[Price] > 0
),
TOPCOUNT(
NONEMPTY(
EXISTING
[Dim Price].[Price].[Price]
*
[Dim Products].[Product].currentmember
*
[Dim Date].week.currentmember,
[Measures].[Price Count]
),
1,
[Measures].[Price Count]
)
)
I have a scenario where a result set has to be bucketed and assign a frequency.
For example, the following MDX query:
WITH MEMBER [MEASURES].[PERC_1] AS
AGGREGATE ( EXISTING [DIM CUSTOMER].[CUSTOMER ID].[ALL].CHILDREN,[MEASURES].[AMOUNT])
SELECT
[MEASURES].[PERC_1] ON 0,
[DIM CUSTOMER].[CUSTOMER ID].CHILDREN,[DIM CUSTOMER].[NAME].CHILDREN
FROM [ANALYSIS DW]
WHERE ([DIM CUSTOMER].[ADDRESS].[ALL])
should return this result:
Perc1
C1 10
C2 0
C3 20
C4 30
C5 40
C6 50
C7 50
C8 50
C9 90
C10 100
Now, I want this result set to be divided into buckets. If my bucket size is 3, the buckets should be
0-30
31-60
61-100
These buckets are calculated based on the maximum and minimum values of the perc_1 measure above; i.e., 0 is minimum and 100 is maximum. Buckets are calculated as (0+100)/3 -- (0-30, 31-60, 61-100).
Now the results after the frequency distribution on the above result set should look as below -
frequency
0-30 4
31-60 4
61-100 2
I will not get the access to the OLTP design/SSAS Cube solution.
WITH SET [0-30 set] AS
Filter([DIM CUSTOMER].[CUSTOMER ID].CHILDREN,
[MEASURES].[PERC_1] >= 0 AND [MEASURES].[PERC_1] <= 30
)
SET [31-60 set] AS
Filter([DIM CUSTOMER].[CUSTOMER ID].CHILDREN,
[MEASURES].[PERC_1] >= 31 AND [MEASURES].[PERC_1] <= 60
)
SET [61-100 set] AS
Filter([DIM CUSTOMER].[CUSTOMER ID].CHILDREN,
[MEASURES].[PERC_1] >= 61 AND [MEASURES].[PERC_1] <= 100
)
MEMBER [DIM CUSTOMER].[CUSTOMER ID].[0-30] AS
NULL
MEMBER [DIM CUSTOMER].[CUSTOMER ID].[31-60] AS
NULL
MEMBER [DIM CUSTOMER].[CUSTOMER ID].[61-100] AS
NULL
MEMBER [Measures].[frequency] AS
CASE [DIM CUSTOMER].[CUSTOMER ID].CurrentMember
WHEN [DIM CUSTOMER].[CUSTOMER ID].[0-30] THEN
[0-30 set].Count
WHEN [DIM CUSTOMER].[CUSTOMER ID].[31-60] THEN
[31-60 set].Count
WHEN [DIM CUSTOMER].[CUSTOMER ID].[61-100] THEN
[61-100 set].Count
END
SELECT { [Measures].[frequency] } ON 0,
{
[DIM CUSTOMER].[CUSTOMER ID].[0-30],
[DIM CUSTOMER].[CUSTOMER ID].[31-60],
[DIM CUSTOMER].[CUSTOMER ID].[61-100]
} ON 1
FROM [ANALYSIS DW]
WHERE ([DIM CUSTOMER].[ADDRESS].[ALL])
I do not think you can do this completely within MDX in a way that the "3" is a parameter to the MDX query, as you need at least to have something like the member definitions for the buckets explicitly in the MDX statement. The WITH clause (or a session level CREATE statement) is the only place where you can create the members shown on the row axis, even if they are just used as placeholders and do not contain any logic.
You would need an external tool to generate a parameter specific MDX statement like that above.
By using the answer of MDX on multiple hierarchical dimensions I have the following MDX query:
with
member L1Y1 as ([Dim Location].[Hierarchy].[Center].&[1],
[Dim Date].[Calendar Date].[Year].&[2010],
[Measures].[x])
select ([Dim Attribute].[Parent Code].&[10000]) on 0,
({L1Y1}) on 1
from DS
Now the problem is how to filter the L1Y1 based on its children. For example suppose we want to filter it so that only season 2 and month 7 included in the query. The following query output is the same as above and the where clause has no effect:
with
member L1Y1 as ([Dim Location].[Hierarchy].[Center].&[1],
[Dim Date].[Calendar Date].[Year].&[2010],
[Measures].[x])
select ([Dim Attribute].[Parent Code].&[10000]) on 0,
({L1Y1}) on 1
from DS
where [Dim Date].[Calendar Date].[Season].&[2] and
[Dim Date].[Calendar Date].[Month].&[7]
Unless you removed the attributes you should have multiple hierarchies available in your time dimension. Can you try this :
with
member L1Y1 as ([Dim Location].[Hierarchy].[Center].&[1],
[Dim Date].[Calendar Date].[Year].&[2010],
[Measures].[x])
select ([Dim Attribute].[Parent Code].&[10000]) on 0,
({L1Y1}) on 1
from DS
where [Dim Date].[Season].&[2] and [Dim Date].[Month].&[7]
Note, as we are not using the hierarchy [Calendar Date] time member is not overwritten but filtered.
How about:
with
member L1Y1 as ([Dim Location].[Hierarchy].[Center].&[1],
[Dim Date].[Calendar Date].[Year].&[2010],
[Measures].[x])
member S2 as ([Dim Location].[Hierarchy].[Center].&[1],
[Dim Date].[Calendar Date].[Season].&[2],
[Measures].[x])
member M7 as ([Dim Location].[Hierarchy].[Center].&[1],
[Dim Date].[Calendar Date].[Month].&[7],
[Measures].[x])
select ([Dim Attribute].[Parent Code].&[10000]) on 0,
(L1Y1, S2, M7) on 1
from DS
I understand it is a somewhat more laborous approach, but you would get the result. If you otherwise want to get a single value only you can try keeping only the M7 measure.