Summing up multiple MDX queries in SSAS - sql-server

i need to SUM the results of multiple queries.
the challenge that i have is that each query has defined members (to calculate a date range)
i need to be able to combine/sum those members across multiple mdx queries
WITH Member [M1] AS Sum(DateRange, Measure)
SELECT [M1]
FROM [Cube]
WHERE {[x].&[y]}
WITH Member [M1] AS Sum(Different DateRange, Measure)
SELECT [M1]
FROM [Cube]
WHERE {[z].&[q]}
each query selects the same members based on different criteria.
the only way i can think of doing this is a UNION and than SUM([M1]) but no idea how that is possible in MDX
UPDATE - in reply to icCube question, here is why i need to have a separate WHERE clause for each query:
i need separate WHERE sections for each query because i need to aggregate the results of different slices. and my slices are defined by n number of dimensions. i emit the mdx query for each slice dynamically based on user configuration input (and construct my WHERE clause dynamically to filter by user preferences). Users are allowed to configure overlapping slices (these are the ones i need to sum up together). then I need to combine these slice row counts into a report. The way i am doing is by passing a string with MDX query to a report. but since i can't think of a way to get multiple queries into one executable string, (nor do i know how many queries there will be) this approach is no longer possible (unless there is some way to union / sum them.
The only way i could think of accomplishing this for now, is with additional batching step that will iterate through all queries, process them (using Adomd.net) into a staging table, and then i can aggregate them into a report using SQL sum(..). Biggest disadvantage to this approach being additional system to be maintained and more possibilities that the data in the report will be stale.

Not sure if this is what you're looking
WITH Member [M1] AS Sum(Different DateRange, ([z].&[q],Measure) ) +
Sum(DateRange, ([x].&[y],Measure))
SELECT [M1]
FROM [Cube]
or
WITH Member [M1] AS Sum(Different DateRange * {[z].&[q]}, Measure ) +
Sum(DateRange * {[x].&[y]}, Measure)
SELECT [M1]
FROM [Cube]
I don't know any way adding the result of two selects in MDX...

I believe you need Aggregate() not Sum.

You could implement the UNION behavior in MDX using SubCubes on this way:
Select
{...} On Columns,
{...} On Rows
From (
Select
{
{Dimension1.Level.Members * Dimension2.&[1] * Dimension3.&[2]},
{Dimension1.&[X] * Dimension2.Members * Dimension3.&[5]}
} On Columns
From [Cube]
)

Related

Oracle Query with Unknown WHERE clause

We have a table with 100 columns. The end user is allowed to write any query trying to search on practically any column.
Essentially, they construct the query dynamically from a screen and the WHERE condition can have any number or combination of columns.
Example
select * from my_tab where col1=x
select * from my_tab where col1=x and col2=y and ....col10 =q
select * from my_tab where col10=a and col20=4 and col30=r
While this is possible syntactically, the biggest problem is performance because you cannot have all possible combination of indexes.
I know this seems to be "query from hell" but still :
What can be other approaches ( both - technical and non-technical ) to this problem ?

Oracle spatial SDO_RELATE: why better performance result from UNION ALL/INTERSECT combined individual specified mask

Initially I was trying to find out why it's so slow to do a spatial query with multiple SDO_REALTE in a single SELECT statement like this one:
SELECT * FROM geom_table a
WHERE SDO_RELATE(a.geom_column, SDO_GEOMETRY(...), 'mask=inside')='TRUE' AND
SDO_RELATE(a.geom_column, SDO_GEOMETRY(...), 'mask=anyinteract')='TRUE';
Note the two SDO_GEOMETRY may not be necessary the same. So it's a bit different from SDO_GEOMETRY(a.geom_column, the_same_geometry, 'mask=inside+anyinteract')='TRUE'
Then I found this paragraph from oracle documentation for SDO_RELATE:
Although multiple masks can be combined using the logical Boolean
operator OR, for example, 'mask=touch+coveredby', better performance
may result if the spatial query specifies each mask individually and
uses the UNION ALL syntax to combine the results. This is due to
internal optimizations that Spatial can apply under certain conditions
when masks are specified singly rather than grouped within the same
SDO_RELATE operator call. (There are two exceptions, inside+coveredby
and contains+covers, where the combination performs better than the
UNION ALL alternative.) For example, consider the following query using the logical
Boolean operator OR to group multiple masks:
SELECT a.gid FROM polygons a, query_polys B WHERE B.gid = 1 AND
SDO_RELATE(A.Geometry, B.Geometry,
'mask=touch+coveredby') = 'TRUE';
The preceding query may result in better performance if it is
expressed as follows, using UNION ALL to combine results of multiple
SDO_RELATE operator calls, each with a single mask:
SELECT a.gid
FROM polygons a, query_polys B
WHERE B.gid = 1
AND SDO_RELATE(A.Geometry, B.Geometry,
'mask=touch') = 'TRUE' UNION ALL SELECT a.gid
FROM polygons a, query_polys B
WHERE B.gid = 1
AND SDO_RELATE(A.Geometry, B.Geometry,
'mask=coveredby') = 'TRUE';
It somehow gives the answer for my question, but still it only says: "due to internal optimizations that Spatial can apply under certain conditions". So I have two questions:
What does it mean with "internal optimization", is it something to do with spatial index? (I'm not sure if I'm too demanding on this question, maybe only developers in oracle know about it.)
The oracle documentation doesn't say anything about my original problem, i.e. SDO_RELATE(..., 'mask=inside') AND SDO_RELATE(..., 'maks=anyinteract') in a single SELECT. Why does it also have very bad performance? Does it work similarly to SDO_RELATE(..., 'mask=inside+anyinteract')?

MDX query is very slow and returns memory exception in SSRS

I'm trying to get a detailed list of all records where my total amount is more than 100k from the following Multidimensional Expressions (MDX) query:
with member [measures].[total] as
[Measures].[m1] + [Measures].[m2] + [Measures].[m3]
select non empty
[measures].[total] on columns,
non empty filter ([dim1].[h1].allmembers
* [dim1].[h2].allmembers
* [Loss Date].[Date].[Year].allmembers
* [Dim1].[h3].allmembers
, [measures].[total]>100000 and [Measures].[Open File Count]>0) on rows
from [Monthly Summary]
where ([1 Date - Month End].[Month End Date].[Month].&[20120331])
Although I get fast results from creating a stored procedure and the final result is less than 1000 rows, my MDX query runs for ever in SSMS and in SSRS returns a memory exception. Any idea on how to optimize or enhance it?
You could use Having instead of Filter, since it is applied after the Non Empty and you may get better performance (see this excellent blog post by Chris Webb). This would be the new version of the query:
with member [measures].[total] as
[Measures].[m1] + [Measures].[m2] + [Measures].[m3]
select non empty
[measures].[total] on columns,
non empty
[dim1].[h1].allmembers
* [dim1].[h2].allmembers
* [Loss Date].[Date].[Year].allmembers
* [Dim1].[h3].allmembers
having [measures].[total]>100000 and [Measures].[Open File Count]>0 on rows
from [Monthly Summary]
where ([1 Date - Month End].[Month End Date].[Month].&[20120331])
I would recommend a couple of changes.
First, do you really want the All member of each of your dimensions to be returned in the query? They will be included if they meet the condition in the filter. Also, I have found changing a where clause to a subselect to perform better in some cases. You need to test to see if it changes performance. Next, you can reduce the number of members that you're filtering by using a NonEmpty function first, by putting it inside the Filter function. Also, in some cases, using a polymorphic operator (*) performs worse than using a CrossJoin function or creating a tuple set of your members. The NON EMPTY on columns is unnecessary when you have only one item on the axis. I've combined all of these suggestions below:
with member [measures].[total] as
[Measures].[m1] + [Measures].[m2] + [Measures].[m3]
select
[measures].[total] on columns,
filter (
nonempty(
([dim1].[h1].[h1].members,
[dim1].[h2].[h2].members,
[Loss Date].[Date].[Year].members,
[Dim1].[h3].[h3].members)
, [measures].[m1]),
, [measures].[total]>100000 and [Measures].[Open File Count]>0) on rows
from
(select [1 Date - Month End].[Month End Date].[Month].&[20120331] on columns
from [Monthly Summary])
See this for a bit of explanation on the NON EMPTY versus NonEmpty: http://blogs.msdn.com/b/karang/archive/2011/11/16/mdx-nonempty-v-s-nonempty.aspx. In some cases putting a NonEmpty function inside a Filter function can produce a performance hit, sometimes not - you need to test.
The problem might be in a dimension or cube design (storage engine problem) and not in the query (formula engine problem). You can diagnose using the techniques here: http://www.microsoft.com/en-us/download/details.aspx?id=661. The whitepaper was written for SSAS 2005, but still applies to later versions of SSAS.
To reduce memory, order your dimensions.
Instead of:
[dim1].[h1].allmembers
* [dim1].[h2].allmembers
* [Loss Date].[Date].[Year].allmembers
* [Dim1].[h3].allmembers
Use
[dim1].[h1].allmembers
* [dim1].[h2].allmembers
* [Dim1].[h3].allmembers
* [Loss Date].[Date].[Year].allmembers
Under the covers, SSAS will inner join the dim1 members and outer join the Loss Date members.

MDX MEMBER causing NON EMPTY to not filter

I'm using an MDX query to pull information to support a set of reports. A high degree of detail is required for the reports so they take some time to generate. To speed up the access time we pull the data we need and store it in a flat Oracle table and then connect to the table in Excel. This makes the reports refresh in seconds instead of minutes.
Previously the MDX was generated and run by department for 100 departments and then for a number of other filters. All this was done in VB.Net. The requirements for filters have grown to the point where this method is not sustainable (and probably isn't the best approach regardless).
I've built the entire dataset into one MDX query that works perfectly. One of my sets that I cross join includes members from three different levels of hierarchy, it looks like this:
(
Descendants([Merch].[Merch CHQ].[All], 2),
Descendants([Merch].[Merch CHQ].[All], 3),
[Merch].[Merch CHQ].[Department].&[1].Children
)
The problem for me is in our hierarchy (which I can't change), each group (first item) and each department (second item) have the same structure to their naming, ie 15-DeptName and it's confusing to work with.
To address it I added a member:
MEMBER
[Measures].[Merch Level] AS
(
[Merch].[Merch CHQ].CurrentMember.Level.Name
)
Which returns what type the member is and it works perfectly.
The problem is that it updates for every member so none of the rows get filtered by NON BLANK, instead of 65k rows I have 130k rows which will hurt my access performance.
Can my query be altered to still filter out the non blanks short of using IIF to check each measurement for null?
You can specify Null for your member based on your main measure like:
MEMBER
[Measures].[Merch Level] AS
IIf(IsEmpty([Measures].[Normal Measure]),null,[Merch].[Merch CHQ].CurrentMember.Level.Name)
That way it will only generate when there is data. You can go further and add additional dimensions to the empty check if you need to get more precise.

List of strings to attribute list

I have a report which was built on MDX-query:
SELECT {[Measures].[IssueOpened] } ON COLUMNS,
{( STRTOSET("[Assigned To].[Id].[Some],[Assigned To].[Id].[Another]") *
[Priorities].[Id].[Id].ALLMEMBERS ) } ON ROWS
FROM (SELECT (STRTOSET(#createdOn) ) ON COLUMNS
FROM [Reports])
I want to change static string "[Assigned To].[Id].[Some]:[Assigned To].[Id].[Another]" to parameter:
SELECT {[Measures].[IssueOpened] } ON COLUMNS,
{( STRTOSET(#assignedTo) *
[Priorities].[Id].[Id].ALLMEMBERS ) } ON ROWS
FROM (SELECT (STRTOSET(#createdOn) ) ON COLUMNS
FROM [Reports])
I have created parameter, but Available values for this paramater is relation dataset (not MDX dimension). Allow multiple values set to Yes.
How can I convert value of parameter to list of atributes: "[Assigned To].[Id].[Some],[Assigned To].[Id].[Another]"?
One way would be to create CLR stored procedure for analysis services which will do it for you, so it would build the SET for you. You can find some examples on google. (i.e. http://andrewdenhertog.com/analysis-services/clr-stored-procedures-in-sql-server-analysis-services-ssas/)
If these come from a relational data source I just encode them in the format that MDX is expecting for the parameter value property for example:
Parameter Label: Some
Parameter Value: [Assigned To].[Id].[Some]
Some time this turns out to be easy to create in TSQL Other times you need to do a little hacking with expressions if you need to support dynamic hierarchies. role playing dimensions would be an example. The basic concept is similar though.

Resources