• +49-(0)721-402485-12
Ihre Experten für XML, XQuery und XML-Datenbanken

Gruppierung nach Wertegleichheit

Die zweite Methode einer Gruppierung in XQuery steht der relationalen Methode insofern näher, als die Gruppendefinition durch die Gleichheit von Ausprägungen bestimmt ist. So bilden beispielsweise alle Personen, die in Berlin leben, eine über Wertegleichheit definierte Gruppe, die keinen direkten Niederschlag in einer hierarchischen XML-Struktur findet. Eine Gruppierung über Wertegleichheit wird somit immer dann angewendet, wenn entweder Entitäten über Eigenschaften zu einer Gruppe zusammengefasst werden sollen, die nicht a priori durch eine hierarchische Struktur repräsentiert werden, oder wenn es sich um flache XML-Daten handelt. Insbesondere der letzte Fall ist durch die XML-artige Darstellung relationaler Datenbankinhalte von wesentlichem Interesse.

Zur Illustration dieser Gruppierungs- und Aggregationsmethodik dient wiederum das vorangegangene Beispiel zur Berechnung des durchschnittlichen Alters des medizinischen Personals pro Berufsgruppe basierend auf folgendem XML-Fragment:

<MedizinischesPersonal>
    <Person><Beruf>Arzt</Beruf>
            <Name>Naumann</Name>
            <Alter>32</Alter> </Person>
    <Person><Beruf>Arzt</Beruf>
            <Name>Shore</Name>
            <Alter>27</Alter> </Person>
    <Person><Beruf>Arzt</Beruf>
            <Name>Meier</Name>
            <Alter>25</Alter> </Person>
    <Person><Beruf>Pfleger</Beruf>
            <Name>Guldenstern</Name>
            <Alter>41</Alter> </Person>
    <Person><Beruf>Pfleger</Beruf>
            <Name>Murawitz</Name>
            <Alter>65</Alter> </Person>
</MedizinischesPersonal>

Die Erzeugung eines Repräsentanten erfolgt in diesem Fall durch Duplikateliminierung unter Verwendung der Funktion fn:distinct-values(), die bereits bei der Einführung des FLWOR-Konstrukts verwendet worden ist. Für das obige Szenario bedeutet dies, dass die Iteration über alle explizit definierten unterschiedlichen Berufsgruppen bzw. unterschiedlichen Berufe (jeweils ein einziges Mal) stattfindet:

<MedizinischesPersonal>
{
for $b in fn:distinct-values(fn:doc("...")//Beruf/text())
let $x := fn:doc("...")//Alter[../Beruf/text() = $b]
return
element {$b}
{<Alter>{ fn:avg($x) }</Alter>}
}
</MedizinischesPersonal>

Die for-Klausel realisiert dabei eine Iteration für die unterschiedlichen Ausprägungen des Elementes Beruf, d. h. über Arzt und Pfleger. Im zweiten Schritt werden an die Variable $x alle Altersangaben gebunden, die bei einem Personaleintrag mit dem entsprechenden Beruf stehen. Das Ergebnis wird dann durch einen berechneten Elementkonstruktor erstellt, wobei das Durchschnittsalter wie im vorangegangenen Fall durch Aufruf der Funktion fn:avg() ermittelt wird.

Im obigen XML-Fragment waren die Werte, die zur Feststellung der Gruppenzugehörigkeit verwendet werden, als textuelle Ausprägung eines Elementes repräsentiert. Als Variante dieser Darstellung existiert zum Beispiel noch eine Gruppenbildung über einen Attributwert eines Elementes oder über den Elementbezeichner. Beide Möglichkeiten seien am Beispiel gezeigt:

Gruppenbildung über Attributausprägungen

<MedizinischesPersonal>
<Person Beruf=”Arzt”> <Name>Naumann</Name>
<Alter>32</Alter> </Person>
...

Die Berufszugehörigkeit wird in Form eines Attributwertes beim Element Person angezeigt. Die for- und let-Klauseln ändern sich entsprechend wie folgt:

...
for $b in fn:distinct-values(fn:doc("...")//Person/@Beruf)
let $x := fn:doc("...")//Alter[../@Beruf = $b]
...

Gruppenbildung über Elementbezeichner

<MedizinischesPersonal>
<Person> <Arzt/> <Name>Naumann</Name>
<Alter>32</Alter> </Person>
...

Die Elemente <Arzt/> bzw. <Pfleger/> zeigen in diesem Fall die Zugehörigkeit zu der entsprechenden Berufsgruppe an. Die Anfrage ändert sich in diesem Fall deutlich bei der Feststellung der unterschiedlichen Ausprägungen der Berufsgruppen, da die Duplikateliminierung nicht auf den Elementen, sondern auf den textuellen Bezeichnern erfolgen muss, zu deren Ermittlung ein geschachtelter FLWOR-Ausdruck vonnöten ist:

...
for $b in fn:distinct-values(
for $i in fn:doc("...")//Person/(Arzt|Pfleger)
return
fn:node-name($i))
let $x := fn:doc("...")//Alter[../fn:node-name(.) = $b]
...

Zusammenfassend ist festzuhalten, dass eine Gruppierung und Aggregation mit den normalen FLWOR-Mechanismen realisierbar ist und keine besondere Syntaxerweiterung, wie es beispielsweise in SQL der Fall ist, existieren muss. Die Gruppenbildung ist dabei entweder implizit durch die hierarchische Struktur vorgegeben oder wird explizit – in Analogie zum relationalen Ansatz – wertebasiert durchgeführt.

 

Quelle: "XQuery – Grundlagen und fortgeschrittene Methoden", dpunkt-Verlag, Heidelberg (2004)

<< zurückvor >>