If I run the following there’s a whole section of Customers that are (null) internet sales amount for both 2007 and 2008 – why is this? How do I use EXISTS to filter to just customers who have results for the years in the select
note: The choice of years could vary so InitialSet needs to be context aware hence I've used [Date].[Calendar Weeks].CURRENTMEMBER withing the EXISTS function.
WITH
SET [InitialSet] AS
EXISTS(
{[Customer].[Customer].[Customer].MEMBERS},
[Date].[Calendar Weeks].CURRENTMEMBER,
'Internet Sales'
)
SET [OrderedSet] AS
NONEMPTY
(
ORDER
(
[InitialSet],
[Measures].[Internet Sales Amount],
BDESC
)
,([Measures].[Internet Sales Amount],[Date].[Calendar Weeks].CURRENTMEMBER)
)
SELECT
{
[Date].[Calendar Weeks].[Calendar Year].&[2007],
[Date].[Calendar Weeks].[Calendar Year].&[2008]
} ON 0,
[OrderedSet] ON 1
FROM [Adventure Works]
WHERE (
[Measures].[Internet Sales Amount]
);
Sets are evaluated by Analysis Services by taking the WHERE clause into account, but not using any row or column settings. If you would like to evaluate the sets only for 2007 and 2008, you have to state that.
Actually, the [Date].[Calendar Weeks].CURRENTMEMBER in your first set will refer to the default member of the [Date].[Calendar Weeks] hierarchy, which is the All member.
Related
I got a cube with cadastral information of some neighborhoods of a city. One of the measures is 'cadastral value': the value of the land of a neighborhood.
Now, the city is divided into districts and a district, into neighborhoods (hierarchy with two levels).
The question is: I need to calculate the percentage that the value of each neighborhood represents compared with the parent (the district) and with the total (city), and also the same about the district compared with the city.
How can I do it?
I tried:
WITH MEMBER
[Measures].[Percentage] AS
([Nbh].[Nbh].[Nbh],[Measures].[Cad value].CurrentMember
/[Nbh].[Nbh].[Nbh],[Measures].[Cad value].CurrentMember.Parent)
SELECT
{[Measures].[Percentage]} ON 0,
[Nbh].[Nbh].[Nbh].AllMembers ON 1
FROM Cadastre
Where the dimensions are:
Nbh : Neighborhood
Cad value: Cadastral value
What I get is "error" in every result value, and the explanation is "Current member () : argument (0) type mismatch: expected:'level|hierarchy|dimension', got:'measure'"
What am I doing wrong?
WITH MEMBER [Measures].[Percentage] AS
([Nbh].[Nbh].[Nbh],[Measures].[Cad value].CurrentMember
/[Nbh].[Nbh].[Nbh],[Measures].[Cad value].CurrentMember.Parent)
There are two problems with this:
One, you are using a static set to compute the value of calculated member namely:
[Nbh].[Nbh].[Nbh]
This is NOT [Nbh].[Nbh].CURRENTMEMBER
Second and the bigger mistake: Using the currentmember on a measure. You can't do that. You can use Measures.CURRENTMEMBER but that's about it. It's best used on hierarchies which are used on axes.
That said, your approach is almost legit. You need to fetch the measure value for the parent.
This should work:
WITH MEMBER
[Measures].[Percentage] AS
DIVIDE
(
[Measures].[Cad value],
([Nbh].[Nbh].CURRENTMEMBER.PARENT,[Measures].[Cad value]) //Cad value for parent
)
SELECT
{[Measures].[Percentage]} ON 0,
[Nbh].[Nbh].[Nbh].AllMembers ON 1
FROM Cadastre
Try the following:
WITH MEMBER [Measures].[Parent %] AS
IIF(
[Nbh].[Nbh].CURRENTMEMBER IS [Nbh].[Nbh].[All]
,1
,[Measures].[Cad value] /
(
[Measures].[Cad value],
[Nbh].[Nbh].CurrentMember.Parent
)
), FORMAT_STRING = 'Percent'
SELECT
{[Measures].[Parent %]} ON 0,
[Nbh].[Nbh].[Nbh].AllMembers ON 1
FROM Cadastre;
Including the IIF is a defensive measure. If you switch to showing AllMembers of the complete hierarchy then the All member will be included. Here is an example using AdvWrks:
WITH
MEMBER [Measures].[Parent %] AS
IIF
(
[Product].[Subcategory].CurrentMember
IS
[Product].[Subcategory].[All Products]
,1
,
[Measures].[Internet Sales Amount]
/
(
[Measures].[Internet Sales Amount]
,[Product].[Subcategory].CurrentMember.Parent
)
)
,FORMAT_STRING = 'Percent'
SELECT
NON EMPTY
{[Measures].[Parent %]} ON 0
,NON EMPTY
[Product].[Subcategory].ALLMEMBERS ON 1
FROM [Adventure Works];
The above returns the following:
Without the IIF the expression is the following:
WITH
MEMBER [Measures].[Parent %] AS
[Measures].[Internet Sales Amount]
/
(
[Measures].[Internet Sales Amount]
,[Product].[Subcategory].CurrentMember.Parent
)
,FORMAT_STRING = 'Percent'
SELECT
NON EMPTY
{[Measures].[Parent %]} ON 0
,NON EMPTY
[Product].[Subcategory].ALLMEMBERS ON 1
FROM [Adventure Works];
We get the following because of lack of foresight:
The error is certainly because of this statement is incorrect:
WITH MEMBER
[Measures].[Percentage]
AS ([Nbh].[Nbh].[Nbh],[Measures].[Cad value].CurrentMember/[Nbh].[Nbh].[Nbh],[Measures].[Cad value].CurrentMember.Parent)
Try to make it like this
WITH MEMBER
[Measures].[Percentage]
AS ([Nbh].[Nbh].[Nbh],[Measures].[Cad value])/([Nbh].[Nbh].[Nbh],[Measures].[Cad value])
We have a typical Date Dimension.
I am struggling to write an MDX to list the Dim.Year dimension member and measure contain data strictly for all month.(from Jan-Dec) otherwise exclude the year?.
This:
SELECT
[Measures].[Internet Sales Amount] ON 0
,[Date].[Calendar].[Calendar Year].MEMBERS ON 1
FROM [Adventure Works];
Returns this:
If I just now add in NON EMPTY I should get rid of 2009 and 2010:
SELECT
[Measures].[Internet Sales Amount] ON 0
,NON EMPTY
[Date].[Calendar].[Calendar Year].MEMBERS ON 1
FROM [Adventure Works];
Now returns:
The above is a very simple example.
Other scenarios might require us to get rid of nulls using other functions such as FILTER / NonEmpty / HAVING / IIF.
Edit
To just return years that have 12 months with data I've written the following (a wee bit more complicated than the above!). I will try to simplify later although you will definitely require an additional measure to achieve your goal,
WITH
MEMBER [Measures].[cntMths] AS
Count
(
NonEmpty
(
Descendants
(
[Date].[Calendar].CurrentMember
,[Date].[Calendar].[Month]
,SELF
)
,[Measures].[Internet Sales Amount]
)
)
SELECT
{
[Measures].[Internet Sales Amount]
} ON 0
,NON EMPTY
[Date].[Calendar].[Calendar Year].MEMBERS HAVING
[Measures].[cntMths] = 12 ON 1
FROM [Adventure Works];
Edit (for #sourav_agasti)
This is a solution against Adventure Works which only uses attribute hierarchies i.e. for a cube without a well formed Date dimension:
WITH
MEMBER [Measures].[cntMths] AS
Count
(
NonEmpty
(
[Date].[Calendar Year].CurrentMember
*
[Date].[Month of Year].[Month of Year].MEMBERS
,[Measures].[Internet Sales Amount]
)
)
SELECT
{} ON 0
,[Date].[Calendar Year].[Calendar Year].MEMBERS HAVING
[Measures].[cntMths] = 12 ON 1
FROM [Adventure Works];
This is the equivalent to Sourav's script using the above method:
WITH
MEMBER [Measures].[cntMths] AS
Count
(
NonEmpty
(
[Dim Year].[Year].CurrentMember
*
[Dim Month].[Month].MEMBERS
,[Measures].[Foo]
)
)
SELECT
{} ON 0
,[Dim Year].[Year].[Year].MEMBERS HAVING
[Measures].[cntMths] = 12 ON 1
FROM [Your Cube];
Further Edit
I chanced on an article last night which gives a more efficient method. Apparently Count - NonEmpty which I've done above is not tuned to work in block calculation mode whereas Sum -IIF is. So here is a quicker alternative using the later method:
WITH
MEMBER [Measures].[cntMths - S] AS
Sum
(
[Date].[Month of Year].[Month of Year].MEMBERS
,IIF
(
IsEmpty([Measures].[Internet Sales Amount])
,null
,1
)
)
SELECT
{[Measures].[cntMths - S]} ON 0
,[Date].[Calendar Year].[Calendar Year].MEMBERS HAVING
[Measures].[cntMths - S] = 12 ON 1
FROM [Adventure Works];
I took it as a challenge to write a code which gets you the result without there being any hierarchies anywhere. So here goes my attempt(after few hours of madness!).
You must be having a [Dim Month] dimension too. I am assuming the data there is stored like Dec-2014 or Dec 2014. Basically assuming that the last 4 digits give the year.
Now, one way you can figure out the years having data is to first list out all the months which don't have data and then figuring out the year for these months and then NOT displaying these years in the final output.
The below code does that for you:
WITH SET MonthsWithNoData AS
FILTER([Dim Month].[Month].CHILDREN, [Measures].[foo] = 0)
MEMBER [Measures].Year as
RIGHT([Dim Month].[Month].CURRENTMEMBER.member_value, 4)
SET SetOfYearsWithNoData AS
GENERATE(MonthsWithNoData, STRTOSET("[Dim Year].[Year].&[" + RIGHT(MonthsWithNoData.currentmember.member_value, 4) + "]"))
SET SetOfYearsWithData AS
([Dim Year].[Year].MEMBERS - SetOfYearsWithNoData)
member yearValues as
[Dim Year].[Year].currentmember.member_value
member wellFormedyearValues as
[Dim Year].[Year].currentmember.member_unique_name
SELECT {yearvalues, wellFormedyearValues} on 0,
SetOfYearsWithData on 1
from [Your cube]
I agree that the final output does not look too beautiful though. Having said that, a hierarchy would make the code much less complicated and the MDX would be much simpler. A [Calender] dimension with requisite hierarchies in place(as assumed in #whytheq's answer) would be the better approach in terms of elegance as well as performance.
I am trying to select the top 10 products by internet sales from the Adenture Works cube (the cube I managed to compile with the Analysis Services Tutorial), I managed to do the cube perfectly, now I need to add a filter to add a specific product line and a given month and I don't know how to build the query...
I have this working:
with
set productNames as head(order({[Product].[Model Name].children}, [Measures].[Internet Sales-Unit Price], desc), 10)
select [Measures].[Internet Sales-Unit Price] on 0,
productNames on 1
from [Analysis Services Tutorial]
I added the filter and the result is the same...
with
set productNames as head(order(
filter({[Product].[Model Name].children},[Product].[Product Model Lines].[Product Line].&[R] )
, [Measures].[Internet Sales-Unit Price], desc), 10)
select [Measures].[Internet Sales-Unit Price] on 0,
productNames on 1
from [Analysis Services Tutorial];
Note: I can't use the hierarchy, because on my production database (which is not adventure works) I don't have hierarchies setup for the given problem.
Take a look at this query:
SELECT
[Measures].[Internet Sales Amount] ON COLUMNS
, TOPCOUNT([Product].[Product Line].&[R]*[Product].[Model Name].[Model Name],10,[Measures].[Internet Sales Amount]) ON ROWS
FROM
[Adventure Works]
The FILTER function is designed to filter a set of members that conform to a particular condition e.g. having Sales greater than £1000. It is not suitable for filtering a set by other dimensions or attributes. For this you can use the CROSSJOIN as I have done above (the *) and also the NONEMPTY function.
I hope that helps,
Ash
I am trying to create a dataset for an SSRS report as documented here:
http://sqlblog.com/blogs/stacia_misner/archive/2010/10/08/29249.aspx
The challenge is that I have multiple measures who's data I want to include in the measure column and I want to include the name of the measure in the RowValue column. So where the following query returns only data for measure "Sales Amount":
with
member [Measures].[Measure] as [Measures].[Sales Amount]
member [Measures].[RowValue] as [Product].[Category].CurrentMember.Name
member [Measures].[ColumnValue] as [Date].[Calendar Year].CurrentMember.Name
select {[Measures].[Measure], [Measures].[RowValue], [Measures].[ColumnValue]} on columns,
non empty ([Product].[Category].[Category].Members, [Date].[Calendar Year].[Calendar Year].Members) on rows
from [Adventure Works]
What I want to do is run the following type of query but have the data returned in the structure of the query above which would allow me to plug it into an SSRS report matrix:
WITH
MEMBER measures.SalesAmount AS [Measures].[Sales Amount]
MEMBER measures.CustomerCount AS [Measures].[Customer Count]
MEMBER measures.InternetFreightCost AS [Measures].[Internet Freight Cost]
SELECT [Date].[Calendar Year].[Calendar Year].Members ON COLUMNS,
{measures.SalesAmount,measures.CustomerCount,measures.InternetFreightCost} ON ROWS
FROM [Adventure Works]
Do any of the MDX ninjas know if this is even possible with MDX?
with member [Geography].[City].[Sales Amount] as 1
member [Geography].[City].[Customer Count] as 1
member [Geography].[City].[Freight Cost] as 1
member [Measures].[RowValue] as [Geography].[City].CurrentMember.Name
member [Measures].[ColumnValue] as [Date].[Calendar Year].CurrentMember.Name
member [Measures].[Measure] as
CASE
WHEN [Geography].[City].CurrentMember IS [Geography].[City].[Sales Amount]
THEN ([Measures].[Internet Sales Amount], [Geography].[City].[All Geographies])
WHEN [Geography].[City].CurrentMember IS [Geography].[City].[Customer Count]
THEN ([Measures].[Customer Count], [Geography].[City].[All Geographies])
WHEN [Geography].[City].CurrentMember IS [Geography].[City].[Freight Cost]
THEN ([Measures].[Internet Freight Cost], [Geography].[City].[All Geographies])
END
select {[Measures].[RowValue], [Measures].[ColumnValue], [Measures].[Measure]}
on columns,
{ [Geography].[City].[Sales Amount], [Geography].[City].[Customer Count], [Geography].[City].[Freight Cost]}
*
[Date].[Calendar Year].[Calendar Year].Members
having [Measures].[Measure] <> null
on rows
from [Adventure Works]
should deliver what you want. I used [Geography].[City] as an utility hierarchy. This can be any hierarchy unused in the query. I chose this one, as it is unrelated to both measure groups used in the query, and hence very unlikely to be used in any query. Some Cube designers create one or two one-member dummy dimensions in their cubes that are unrelated to any measure group, and can be used just like here in order to create calculated members on them.
One of the difficulties with ReportingServices queries is that measures must always be in the columns, and no other hierarchy may be in the columns. Hence, if we want to have the measures in the rows, we must move them to another hierarchy. This is done in two steps: First, we create dummy members on the utility hierarchy, and then map these to the measure needed in the CASE construct of the [Measures].[Measure] definition, where we need to use the default member of the utility dimension (in most cases the All member) in order to get something different than the 1 that I used for the dummy value.
Finally: non empty does not work properly with this construct, as [Measures].[RowValue] and [Measures].[ColumnValue] are never null. Hence I replaced it by HAVING, which can look at specific column values within the row.
Using the Adventure works Cube, if I run the following code (from MS example):
with
Member [Measures].[Internet Sales Amount - Range]
AS aggregate ( [Date].[Fiscal].[Date].&[20080430]:[Date].[Fiscal].[Date].&[20080502] , [Measures].[Internet Sales Amount] )
SELECT
{ [Measures].[Internet Sales Amount - Range] } ON COLUMNS,
{ [Product].[Category].Members } ON ROWS
FROM
[Adventure Works]
You get the proper results.
However, when I implement similar functionality via the SCOPE command in a calculated tab:
scope ([Product].[Category], [Measures].[Internet Sales Amount]);
this = aggregate ( [Date].[Fiscal].[Date].&[20080430]:[Date].[Fiscal].[Date].&[20080502] , [Measures].[Internet Sales Amount] );
end scope;
and then run the following mdx query:
SELECT
{ [Measures].[Internet Sales Amount] } ON COLUMNS,
{ [Product].[Category].Members } ON ROWS
FROM
[Adventure Works]
I get vastly different results. The scope appears to be ignoring the date range or ignoring the category members, i'm not sure what. I am having a similar issue on my cube when creating a new scope with a date range.
Anyone know what's going on with the scope?
Use
CREATE MEMBER CurrentCube.[Measures].[Internet Sales Amount - Range2] AS NULL;
scope ([Measures].[Internet Sales Amount - Range2]);
this = aggregate ( [Date].[Fiscal].[Date].&[20080430]:[Date].[Fiscal].[Date].&[20080502] , [Measures].[Internet Sales Amount] );
end scope;
Otherwise, there might be an infinite recursion as you reference the measure inside the scope which you use in the SCOPE itself as well.