Blog Article & Copyright by Lukas Hillesheim
Attribute Relationships sind interne Objekte der Analysis Services MultiDimensional Engine. Sie sind vom MDX-Client aus nicht sichtbar, nur indirekt zu nutzen und nur in der Entiwcklungs-Umgebung konfigurierbar. Sie wirken sich aber auf MDX-Objekte und implizite Verhaltensweisen aus. Relationships zu verstehen, ist daher grundsätzlich wichtig für das Verständnis von MDX.
1. Allgemeines
Attribute sind die elementaren Bausteine innerhalb von Analysis Services MultiDimensional. Aus ihnen leiten sich Attributs-Hierarchieen, Hierarchieen mit mehreren Ebenen und Element-Eigenschaften ab. Außerdem steuern sie implizite Verhaltensweisen wie MDX [<hierarchy>].CurrentMember und AutoExist.
Für die nachfolgenden Beispiele wird folgendes Datenmodell verwendet:
Extraktion von Attributen aus Tabellen-Spalten. Über Attribute werden die Inhalte von Tabellen-Spalten der Analysis Services Engine zur Verfügung gestellt. Das Mapping von Attributen auf Tabellen-Spalten geschieht im im SSDT-Designer an folgender Stelle:
Im Beispiel gibt es ein Key-Attribut [Customer], das auf die Spalte [dimCustomer].[Id] gemappt ist und in "Customer" umbenannt wurde. Zusätzlich existieren diverse Non-Key-Attribute [City], [Country], [Region] und [Phone No]. Standardmäßig haben alle Attribute eine direkte Relationship zum Key-Attribut:
Bitte beachten Sie, dass es zwei Typen von Relationships gibt: 1. Relationships zwischen Attributen im MultiDimensionalen Cube und 2. Relationships zwischen Tabellen der relationalen Quell-Struktur. Für das Verständnis von MDX sind nur Attribute-Relationships relevant.
Hinweis: Bezüglich der Relationships gibt es einen grundsätzlichen Unterschied zum Analysis Services Tabular. In der Tabularen Umgebung sind die Relationships der relationalen Quellstruktur für den DAX-Client sichtbar und müssen beim DAX-Coding berücksichtigt werden.
2. Attributs-Hierarchieen
Für den MDX-Client macht der MultiDimensionale Cube folgende Objekte sichtbar:
- - Dimension
- - Hierarchie
- - Member
- - Property
- - Measures
Der Unterschied zwischen "Attribute-Hierarchie" und "Hierarchie mit mehreren Ebenen" wird zwar in diesem Artikel berücksichtig, ist aber in syntaktischer Hinsicht nicht relevant.
Ohne weiteren Eingriff des Entwicklers wird zunächst jedes Attribut als Hierarchie exportiert. Liste von Attributen:
Liste von Hierarchieen der Dimension [dCustomer]:
Dieses Standard-Verhalten wird über die Eigenschaften „AttributeHierarchyEnabled“ des Attributs festgelegt. Beispiel für das Attribut [City]:
Die Aggregierbarkeit des Attributs sorgt dafür, dass für die Member der Hierarchie, also z.B. für die einzelnen Städte, Aggregate gebildet werden. Zusätzlich wird ein künstlicher Member [ALL] erstellt und der Hierarchie hinzugefügt. [ALL] stellt den Total der Aggregate dar.
Manche Daten des Cubes sind nicht im Sinne von Aggregation interessant, sondern im Sinne einer Beschreibung. Dies trifft z.B. auf das Attribut [Phone No] zu. Es ist nicht sinnvoll, Aggregate nach Telefon-Nummern zu bilden, aber es ist nützlich, zusätzlich zu einem Kunden auch die Telefon-Nummer anzuzeigen.
Die Deaktivierung der Aggregierbarkeit läßt das Attribut aus der Liste der Hierarchieen verschwinden, aber die Daten des Attributs sind noch immer Teil des Cubes (s.u.):
[Phone No] ist weiterhin Teil der Attributs-Liste; jedoch mit einem anderen Symbol markiert:
Nach außen hin ist [Phone No] nicht mehr Teil der Hierarchie-Liste:
3. Member Properties
Über Attribute-Relationships wird ein Attribut auf der rechten Seite einer Relationship zu einer Property des Attributs auf der linken Seite.
Die Änderung bei der Aggregierbarkeit von [Phone No] hat sich nicht auf die Relationships (s.o.) ausgewirkt. Somit befindet sich [Phone No] weiterhin auf der rechten Seite und [Customer] auf der linken Seite. Anders ausgedrückt: [Phone No] ist eine Member-Property von [Customer]. Diese Tatsache drückt der folgende MDX-Code aus:
Unabhängig von der Tatsache, ob die Aggregierbarkeit aktiviert oder deaktiviert ist, kann bei jeder Attribute-Relationship die jeweilige rechte Seite als Property der linken Seite betrachtet werden. Also sind auch die Attribute [City], [Region] und [Country] Eigenschaften von [Customer]:
4. CurrentMember
Ein weiterer Effekt von Attribute Relationships ist, dass die Selektion eines Members auf einer Seite implizit eine Member-Selektion auf der anderen Seite nach sich zieht. Dies funktioniert sowohl von links nach rechts, als auch in ungekehrter Richtung.
Beispiel: Durch die Selektion von [Customer].[John] auf der linken Seite wird [City].CurrentMember implizit auf [City].[Madrid] gesetzt. Umgekehrt gilt: Würde [City].[Madrid] auf der rechten Seite selektiert, ergäbe sich implizit auf der linken Seite [Customer].[ALL]. Bitte nehmen Sie außerdem zur Kenntnis, dass der Zugriff auf [Phone No].CurrentMember einen Fehler verursacht, da die CurrentMember Funktion nur auf eine Hierarchie angewandt werden kann: [<hierarchy>].CurrentMember.
Beispiel für eine Attribute Relationship mit impliziter Member-Selektion von links nach rechts:
Das folgende Beispiel zeigt, wie Attribute Relationships von rechts nach links wirken. Während mit Hilfe der Expression "[dCustomer].[City].[City].Members" eine Iteration über die Members der [City] Hierarchie stattfindet, wird pro [City] Member die Measure-Expression "[dCustomer].[Customer].CurrentMember" evaluiert. Die Attribute Relationship steuert implizit [Customer].CurrentMember und überschreibt dabei die Slicer Axis. Die Slicer Axis trägt zum Initial Context mit einer Einschränkung auf [Ann] und [John] bei. Auf Grund der Einschränkung, die sich auf der linken Seite einer Relationship befindet, werden schließlich nur die Städte herausgefiltert, wo [Ann] und [John] residieren. Dies erklärt, warum nur zwei Städte für die Iteration zur Verfügung stehen. Während der Iteration wird dann der Initial Context mit [Ann] und [John] überschrieben durch einen neuen Runtime Context, der [Customer].CurrentMember konstant auf [Customer].[ALL] setzt. Dieses Beispiel zeigt den Effekt von Attribute Relationships in zweifacher Hinsicht!
Zwischen der Dimension [dCustomer] und der Dimension [dProduct] existieren keine Relationship. Relationships verbinden nur Attribute ein und derselben Dimension. Dadurch, dass eine Relationship zwischen [Customer] und [Category] fehlt, kann [Category].CurrentMember nicht modifiziert werden und bleibt konstant [ALL]:
5. Hierarchieen mit mehreren Ebenen
Die in den Attributen einer Dimension gespeicherten Daten können hierarchische Sachverhalte ausdrücken. Beispielsweise befinden sich Kunden in einer bestimmten Stadt, die sich wiederum in einer bestimmten Region befindet. Von „oben“ betrachtet ergibt sich ein Baum – mit einem [ALL]-Member auf dem Top-Level, einem 2nd-Level mit Regionen, einem 3rd-Level mit Städten und einem 4th-Level mit Kunden.
Im Dimensions-Editor lassen sich Hierarchie-aktivierte Attribute zum Aufbau einer solchen Hierarchie mit mehreren Ebenen nutzen. Im Beispiel wird eine Hierarchie [hCustomer] aus den Attributen [Region], [City] und [Customer] erstellt:
Damit die Hierarchie „funktioniert“, gilt es, zwei Bedingungen zu beachten:
1. Es sollten Relationships definiert sein, die das Verhältnis der Level ausdrücken. D.h. das niedrigere Level sollte zum übergeordneten Level eine N:1-Relationship haben. Ohne diese Relationship gibt es entweder Schema-Fehler oder Performance-Probleme. Hinweis: die besonderen Aufgaben, die durch Nichtbeachtung dieser Regel verursacht werden, entstehen durch zahlreiche verschiedene Konstellation und müssen gesondert (in einem anderen Dokument) betrachtet werden.
2. Die Daten müssen den Relationships genügen. Eine als N:1 definierte Relationship verlangt beispielsweise, dass für die Stadt „Madrid“ nur eine Kombination mit der Region „South“ existiert. Sollte beim Aufbereiten der Dimension eine weitere Kombination von „Madrid“ mit einer anderen Region wie z.B. „North“ gefunden werden, bricht der Cube den Aufbereitungsprozess mit Fehler ab.
Relationships für das Beispiel:
Transitive Relationships. Durch die geänderten Relationships ergeben sich weitere Verhaltensweisen: Attribute-Relationships sind transitiv. Beispiel: wenn auf der linken Seite der Relationship „Customer -> City“ der Member [Customer].[John] selektiert wird, ergibt sich nicht nur auf der rechten Seit [City].[Madrid], sondern die transitive Natur der Relationships sorgt zusätzlich dafür, dass auch die nächsten Relationships „City -> Region“ und „City -> Country“ gesteuert werden. Also ergeben sich für [Customer].[John] in direkter Weise [City].[Madrid] und in indirekter Weise [Region].[South] und [Country].[Spain].
Member als Pointer. Die vom Cube-Entwickler definierte Hierarchie mit mehreren Ebenen stellt technisch einen Haufen von Pointern auf die zu Grunde liegen Attribute dar. Der Member [John] aus der Hierarchie [dCustomer].[hCustomer] ist letztlich ein Pointer auf den Member [John] aus der Hierarchie [dCustomer].[Customer]. Im Hintergrund sorgen die Relationships für eine Art „Synchronisierung“ der Pointer.
Das nachfolgende Beispiel zeigt eine Iteration über die Members von [hCustomer]. Im Rahmen der Iteration werden mittels Attribute-Relationship die CurrentMember aller involvierten Hierarchieen modifiziert. Die Iteration schließt alle Member der Hierarchy [hCustomer] ein, also Member auf den Levels "Region", "City" und "Customer". Für Member auf dem Level „Customer“ ergibt sich eine vollständige „Information“ bezüglich [City], [Region] und [Country]. Die Member dieses Levels wie z.B. „Karen“ befinden sich auf der „linkesten“ Seite der Relationships. Durch Transitivität werden alle Hierarchieen und deren CurrentMember der rechten Seite erreicht. Bei Membern des „City“-Levels wie z.B. [Prague] ergibt sich eine unvollständige „Information“. Oder anders ausgedrückt: [Customer].CurrentMember wurde nicht geändert, sondern bleibt [ALL]. Der Grund hierfür ist, dass [City] sich auf der rechten Seite der Relationship befindet und [Customer] auf der linken. Das Modifizieren eines CurrentMembers wirkt aber nur von links nach rechts.
6. AutoExist
Die Frage, ob ein bestimmtes Tupel "existiert", kann aus der Sicht eines Anwenders auf zweiterlei Arten definiert werden:
1. Tupels existieren dann, wenn es einen Wert gibt. Beispielsweise könnte sich für das Tupel ( [East], [2010] ) ein [Amount] von NULL ergeben. Der fachliche Grund könnte sein, dass es Kunden in der Region „East“ erst ab dem Jahr 2018 gab. Nach dieser Regel gibt es das Tupel also nicht. Technisch drückt sich Existenz und Nicht-Existenz bei dieser Regel durch entsprechende existierende oder nicht-existierende Faktenzeilen aus.
2. Tupels existieren dann, wenn das Dimensions-Schema eine Kombination der entsprechenden Member erlaubt. Beispielsweise könnte die Kombination von [Madrid] mit [South] erlaubt sein, weil das Schema eine N:1-Relationship zwischen [City] und [Region] festlegt. Das Tupel ([Madrid], [South]) wäre in diesem Sinne auch dann gültig, wenn der dazugehörige [Amount] NULL ist.
„AutoExist“ ist eine Verhaltensweise der Vertipaq-Engine. Hiermit werden Tupels unterdrückt, die nicht „existieren“ und zwar im Sinne der 2ten Regel. Es werden solche Tupels automatisch ausgeschlossen, deren Existenz auf Grund des Schemas nicht möglich ist. AutoExist wirkt sich auf verschiedenste Konstellationen aus. Am meisten offensichtlich ist die einschränkende Wirkung beim CrossJoin.
Nachfolgend zwei Beispiele. Im ersten Beispiel wird ein CrossJoin zwischen [Region] und [Year] durchgeführt. Da sich beide Hierarchieen in verschiedenen Dimensionen befinden, kann AutoExist keine Einschränkung vornehmen.
In zweiten Beispiel wird ein CrossJoin zwischen [Region] und [City] durchgeführt. In diesem Fall entfaltet AutoExist eine einschränkende Wirkung.
Beispiel 1: [Region] CrossJoin [Year]. Das vollständige kartesische Produkt wird gebildet.
Beispiel 2. [Region] CrossJoin [City]. Kein vollständiges kartesisches Produkt. Jede Region taucht nur einmal im Ergebnis auf: