Do levels have members or is it just hierarchies? - ssas

can someone definitively tell me why
[Dimension].[Hierarchy].[Level].&[(Unknown)] doesn't make sense
while
[Dimension].[Hierarchy].[Level].&[some_other_member] does
and yet both [Dimension].[Hierarchy].&[(Unknown)] and [Dimension].[Hierarchy].&[some_other_member]
both do
To me isn't unknown simply the case where the data doesn't fall into a defined hierarchy member?
this area of SSAS seems a bit opaque to me.
Any link to the official definition would be great.

Each member is at one level of a hierarchy. If you have a standard attribute hierarchy, then you have two levels: The All level containing the All member and the level named like the hierarchy, which contains all the members found in the attribute column of the relational dimension table as well as the Unknown member. The latter is contained on that level, as it is clearly not part of the All level, and it is included in the sum of all members of its level to give the numbers for the All member.
The official documentation of the UnknownMember function describes what I described above and some special cases like the case that an attribute hierarchy has set the IsAggregatable property to false (i. e. the All level is missing, an the level named like the attribute is to only one, end hence the top level).

Related

Why does dimensionality depend on the attribute in MDX

For the life of me I cannot figure out why MDX defines dimensionality per-attribute on a dimension rather than on the key. Perhaps I'm misunderstanding something here, but it seems like a very odd way to do this if I'm understanding things correctly. Let's say I have the following data:
Person
ID (Key)
Name
Age
And I have some data like this: [('Tom123', 'Tom', 15), ('Brad456', 'Brad', 16).
Now, why I could select the two users the following two ways:
{Person.Name.Tom, Person.Name.Brad}
Or:
{Person.ID.Tom123, Person.ID.Brad456}
But not the following way:
{Person.Name.Tom, Person.ID.Brad456}
Yet all three use the same 'dimension' and even 'dimensionality' since all three ways uniquely address the same two Person entities!
This seems so odd to me, in that they are both using the same 'dimension' and 'dimensionality' and should be able to use the Key for that dimension rather than thinking each attribute is unique. Why is this so? Or, am I misunderstanding something in this.
If we use this image:
Why would it matter if we address the individual cube (tuple) by doing: {Product.TV, Geography.Asia, Time.Q1} or doing {Product.TV, Geography.Asia, Time.Quarter One}. They're just two ways of doing exactly the same thing but yet MDX considers them different dimensionality (?).
That is an excellect question.
Yet all three use the same 'dimension' and even 'dimensionality' since
all three ways uniquely address the same two Person entities!
This seems so odd to me, in that they are both using the same
'dimension' and 'dimensionality' and should be able to use the Key for
that dimension rather than thinking each attribute is unique. Why is
this so? Or, am I misunderstanding something in this.
So for any language, the syntax is checked before anything else. The case you are refering is the only instance where Dimensionality can be ignored. But it will not be wise for a language to go evaluate the data first(in terms of SSAS and MDX its called AttributeID). Secondly this will be more confusing to a user. building on your example
{Person.Name.Tom, Person.ID.Brad456}
lets we have 100 people in Newyork, so as per your logic the following
the set will be {Person.City.Newyork}, then MDX will replace all 100 IDs. This would prevent MDX from using Aggregates, which is the biggest advantge of a CUBE. Mostly the queries sent to a Cube are targeted towards summarized data. Most queries in MDX would need data of entire NEWYORK rather then a single person in NEWYORK
So to summarize, the compile time will increase and the Aggregates will not be useable.

Trouble with DIMENSION_PROPERTIES

I'm doing some exploratory work with tiny test dimensions and cubes. I'm hoping to finally fully understand SSAS's concept of a "dimension attribute", which I find pretty incomprehensible, though I've used SSAS for years without really getting to the bottom of it.
But that's too broad a question. My problem now is this:
I've created an Employee dimension. Key column is EID (int), Name column is Name (varchar). OK, my naming conventions aren't brilliant (but good naming conventions seem to be very difficult in SSAS dimension design, given the fact that all object names are exposed to users).
There is also an attribute called Salary.
What I'm trying to do here is explore the possibility of a "dimension leaf-level property". Not really "dimension attributes" in the sense SSAS uses them, though the only way to implement them is as dimension attributes. What I mean by a "leaf-level property" is a non-aggregatable "attribute", with the same cardinality as the leaf level (or, in any case, to be treated as having the same cardinality). I don't want to aggregate by Salary, for the purposes of this exercise: I just want Salary to be available as a property of each leaf-level member of the dimension. A bit like an extension of the Key Column and Name Column properties.
I'm familiar with this common way of showing member properties:
WITH MEMBER Measures.ESal AS Employee.EID.CurrentMember.Properties("Salary")
SELECT
Measures.ESal ON 0,
Employee.EID.EID.Members
ON 1
FROM $Employee
This works. To prove that I'm only returning members from the leaf level, here's the result set:
(It makes sense that a member property for a non-leaf level might not have a value - and I've read that in this case, MDX simply throw an error rather than showing values for the leaf-level members and nothing for non-leaf).
But trying to use DIMENSION PROPERTIES causes an error:
SELECT
{} ON 0,
Employee.EID.EID.Members
DIMENSION PROPERTIES Employee.Salary
ON 1
FROM $Employee
Result: Query (4, 22) The [Employee].[Salary] dimension attribute was not found.
If I put the hierarchy and level in, though, it works (though SSMS doesn't actually show anything specified in DIMENSION PROPERTIES; as I'd heard already):
SELECT
{} ON 0,
Employee.EID.EID.Members
DIMENSION PROPERTIES Employee.EID.EID.Salary
ON 1
FROM $Employee
Result: just like before, but with no ESal column (obviously).
Two questions:
Why does the Salary attribute have to be addressed as an attribute
of dimension/hierarchy/level Employee.EID.EID? Surely it's an
attribute in the dimension? (I find the way SSAS/SSDT implements
multiple hierarchies deeply confused and confusing)
What is the point of DIMENSION PROPERTIES? Do other clients
actually show what it returns? If so, isn't it then a nightmare to
test this code?

SSAS: Two sets specified in the function have different dimensionality

I'm trying to run the following MDX query (I'm newbie in the matter):
WITH MEMBER [Measures].[Not Null SIGNEDDATA] AS IIF( IsEmpty( [Measures].[SIGNEDDATA] ), 0, [Measures].[SIGNEDDATA] )
SELECT
{[Measures].[Not Null SIGNEDDATA]} ON COLUMNS,
{[Cuenta].[818000_001],[Cuenta].[818000_G02]} ON ROWS
FROM [Notas_SIC]
WHERE ([Auditoria].[AUD_NA],[Concepto].[CONCEPTO_NA],[Entidad].[CCB],
[Indicador].[INDICADOR_NA],[Interco].[I_NONE],[Moneda].[COP],
[Tiempo].[2010.01],[Version].[VERSION_NA])
Where 818000_001 is a base member of my 'Cuenta' dimension, and 818000_G02 is a node or aggregation. I receive the following message:
"Two sets specified in the function have different dimensionality"
What am I doing wrong? If I put the query with only base members (many) or only differents aggregations, the result is ok as expected.
Thanks in advance!
By using commas in your WHERE clause, you are trying to create a set out of members from different dimensions. You should use asterisks to make a CROSSJOIN instead.
So replace this:
WHERE ([Auditoria].[AUD_NA],[Concepto].[CONCEPTO_NA],[Entidad].[CCB],
[Indicador].[INDICADOR_NA],[Interco].[I_NONE],[Moneda].[COP],
[Tiempo].[2010.01],[Version].[VERSION_NA])
With this:
WHERE ({[Auditoria].[AUD_NA],[Concepto].[CONCEPTO_NA],[Entidad].[CCB]} *
{[Indicador].[INDICADOR_NA],[Interco].[I_NONE],[Moneda].[COP]} *
{[Tiempo].[2010.01],[Version].[VERSION_NA]})
I added curly braces though I'm not sure if they're absolutely required.
This is maybe your problem:
{[Cuenta].[818000_001],[Cuenta].[818000_G02]} ON ROWS
You have put them as a set but you can only make a set out of members with the same dimensionality. From your description it sounds like [Cuenta].[818000_G02] is being classed as a different hierarchy which is unexpected.
Is [Cuenta].[818000_G02] created using the Aggregate function? Can you swap to using the Sum function? Does the script then work?
(not a great answer - just more questions?)
{[Cuenta].[818000_001],[Cuenta].[818000_G02]}
Your problem probably lies in the above statement. As is clear, they could be from different hierarchies(which is not clear from your example and I come to that below).
Try replacing the above with
{[Cuenta].[Hierarchy1].[818000_001]} * {[Cuenta].[Hierarchy2].[818000_G02]}
where Hierarchy1 and Hierarchy2 are the hierarchies to which these members belong. (If you are not sure, just try {[Cuenta].[818000_001]} * {[Cuenta].[818000_G02]}). I am assuming that the second aggregate members may be built on a different hierarchy and thus the engine is throwing an error.
It is generally a good habit to always use the fully qualified member name because then the SSAS engine has to spend less time in searching for the member.

NHibernate query with restriction on child collection

I've looked at plenty of examples on this site, but I'm still not sure how to do this:
For illustration, let's say I have persistent Venues, each of which has a collection of Events, where each Event has ReservationDate. If I want to get all the Venues whose next Event is of type "Wedding", how would I go about it? It requires selecting based on a value of a specific element (in this case the first ReservationDate > Today) in the child collection, that element being determined by a different restriction (Type == "Wedding").
I've looked at various queries using CreateCriteria, QueryOver, DetachedCriteria, JoinOver and the whole gamut of NH query options (I don't want to use HQL), but I'm still at a loss.
Your help is appreciated.
Michael
I've created very detailed example how to handle these situations. Please see all the details here:
Query on HasMany reference
The point is to create few Subqueries represented as DetachedCriteria. Using aliasing we can communicate among them (passing the ID).
At the end, we can SELECT clean/flat structure of the ROOT entity... while having full power of filtering based on referenced collecitons.
This approach has the biggest advantage in the fact, that we can apply the paging (Take(), Skip()) because the final select is on top of the root table

Refering to a particular parent, in case of multiple, and then retrieving its attribute

If an sobject has more then one parent, how do we lexically refer any one its parent in order to get its attributes?
I need it to write a naming convention for that particular sobject.
The sobject and its parent sobjects are connected in the schema by code.
What I tried was something like:
{project.code}/{sobject.parent01_code}/{sobject.code}/{context}
which works but {sobject.parent01_code} is not what I want, because it is not quite self-explanatory and cryptic to be used for naming of files and directories.
I rather want to something like ../{sobject.parent01.name}/.. or ../{sobject.parent01_code.name}/.. which returns Reported Error: "too many values to unpack" error.
So how can I achieve such a thing? Given, if I am not wrong, the absence of a full brunt expression language in the setting of naming conventions, which, if a present, would enable something like #SOBJECT(parent01["code", {sobject.parent01_code}]).name.
These are two separate questions but put into one because it relates to one particular problem.
This used to be unsolved in earlier versions of tactic. In 4.1 however, you can also use the expression language in the braces.
ex: {project.code}/{#GET(example/some_stype.name)}/versions
If some_stype is the parent of to the current stype's, you'll get the corresponding sobject's name.