Gruppierung nach Struktur
Der erste Schritt der Gruppierung bedeutet inhaltlich, dass aus einer Menge von Einträgen mit hinsichtlich des Gruppierungsattributes gleichen Ausprägungen nur ein Repräsentant in das Ergebnis übernommen wird. Ähnlich der Schreibweise in SQL, wo zwingend erforderlich ist, dass alle zur Gruppierung verwendeten Attribute in der SELECT-Klausel stehen müssen, werden in XQuery die zur Gruppierung verwendeten Variablen in einer for-/let-Klausel initialisiert. Wird die Gruppierungsrichtung durch die Hierarchie vorgegeben, ist – im Gegensatz zur Duplikateliminierung bei einer Gruppierung über gleiche Werte – nur eine Aggregationsfunktion über die "Kindelemente" des Zielknotens der Gruppierung zu verwenden. Der Vertreter einer Gruppe wird somit durch den darüber stehenden Knoten repräsentiert.
Als Beispiel dient das nachfolgende XML-Fragment, in dem das medizinische Personal in Ärzte und Pflegepersonal untergliedert ist.
<MedizinischesPersonal>
<Ärzte>
<Arzt> <Name>Naumann</Name> <Alter>32</Alter> </Arzt>
<Arzt> <Name>Shore</Name> <Alter>27</Alter> </Arzt>
<Arzt> <Name>Meier</Name> <Alter>25</Alter> </Arzt>
</Ärzte>
<Pflegepersonal>
<Pfleger> <Name>Guldenstern</Name> <Alter>41</Alter> </Pfleger>
<Pfleger> <Name>Murawitz</Name> <Alter>65</Alter> </Pfleger>
</Pflegepersonal>
</MedizinischesPersonal>
Auf diesem XML-Fragment soll als Ziel der Gruppierung und Aggregation das Durchschnittsalter pro Berufsgruppe bestimmt werden. Als Gruppenmitglieder gelten jeweils die einzelnen Arzt- bzw. Pfleger-Elemente; als Repräsentant wird jeweils das – bereits in der Struktur existierende – Oberelement Ärzte bzw. Pflegepersonal verwendet, so dass folgendes Ergebnisdokument daraus resultieren soll:
<MedizinischesPersonal>
<Ärzte> <Alter>28</Alter> </Ärzte>
<Pflegepersonal> <Alter>53</Alter> </Pflegepersonal>
</MedizinischesPersonal>
Die Anfrageformulierung orientiert sich dabei an der OQL-Syntax, indem die Menge der zu aggregierenden Elemente als Parameter der Funktion fn:avg() übergeben werden.
<MedizinischesPersonal>
{
for $p in fn:doc("...")//MedizinischesPersonal/*
let $x := $p/*/Alter
return
element { fn:node-name($p) }
{ <Alter>{ fn:avg($x) }</Alter> }
}
</MedizinischesPersonal>
Die sich der Gruppenbildung anschließende Aggregation erfolgt auf funktionaler Ebene. Im Allgemeinen erwartet jede Aggregationsfunktion (fn:sum(), fn:avg(), fn:count(), fn:min() und fn:max()) eine Sequenz von Einträgen mit gleichem Datentyp. Für das laufende Beispiel zur Berechnung des Durchschnittsalters pro Berufsgruppe muss somit für jede Berufsgruppe die Sequenz mit den unterschiedlichen Altersangaben der Funktion fn:avg() übergeben werden.
Zur Verdeutlichung wird eine Hilfsvariable ($x) eingesetzt, die alle Einträge innerhalb einer Gruppe, d. h. für jede einzelne Berufsgruppe die Altersangaben in Form einer Sequenz, enthält. In diesem Fall der Gruppierung bezüglich eines Vorgängerknotens umfasst $x alle Enkelelemente der aktuellen Berufsgruppe. In der ersten Iteration wird die Variable $x mit dem Wert (32,27,25) besetzt, resultierend in dem Durchschnittsalter von 28 Jahren für die Berufsgruppe der Ärzte. Im zweiten Durchlauf wird $x mit dem Wert (41,65) belegt, womit der Durchschnittswert von 53 Jahren für das Pflegepersonal ermittelt wird.
Quelle: "XQuery – Grundlagen und fortgeschrittene Methoden", dpunkt-Verlag, Heidelberg (2004)
<< zurück | vor >> |