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

Geschachtelte Gruppierung

Als extrem mächtige Eigenschaft, die auf dem Prinzip der Anwendung von Aggregationsfunktionen auf Sequenzen beruht, gilt die Fähigkeit der Schachtelung mit Gruppierungen. Die Überlegung, die sich hinter diesem Grundprinzip verbirgt, besteht darin, dass alle Ausdrücke, die eine Sequenz von Knoten liefern, als Parameter für eine Aggregationsfunktion verwendet werden können.

Da neben einfachen Pfadausdrücken auch beliebig komplexe FLWOR-Ausdrücke einen XQuery-Ausdruck repräsentieren, dürfen (potenziell korrelierte) FLWOR-Ausdrücke als Parameter jeder Aggregationsfunktion auftreten. Ohne die zusätzliche let-Klausel im äußeren FLWOR-Ausdruck könnte die Berechnung des Durchschnittsalters analog auch wie folgt über ein zusätzliches FLWOR-Konstrukt innerhalb der fn:avg()-Funktion erfolgen:

<MedizinischesPersonal>
{
for $b in fn:distinct-values(for $i in fn:doc("...")//
MedizinischesPersonal/*/*
return fn:name($i))
return (<Berufsgruppe> {$b} </Berufsgruppe>,
<Alter>{ fn:avg(let $x := fn:doc("...")//*
[fn:name(.) = $b]/Alter
return $x)} </Alter>)
}
</MedizinischesPersonal>

Der FLWOR-Ausdruck innerhalb der Aggregationsfunktion ist dabei korreliert, da er eine Variable ($b) referenziert, die sich auf einen Kontext außerhalb des Ausdrucks bezieht. Analog zur vorangegangenen Notation wird die let-Klausel bei jeder Iteration der for-Klausel neu ausgewertet.

Die Schachtelung von FLWOR-Ausdrücken ist sowohl in return-Klauseln als auch über Funktionen an die Objektkonstruktion im Bereich objektorientierter Anfragesprachen angelehnt und eröffnet einen weiten Bereich für komplexe Anfragen. An allen Stellen, an denen beispielsweise Aggregationsfunktionen erlaubt sind (zum Beispiel in Form einer Gruppenfilterung innerhalb einer where-Klausel), ist eine Schachtelung von FLWOR-Ausdrücken möglich.

Die Mächtigkeit des Konzeptes sei an folgendem Beispiel gezeigt, in dem die durchschnittlichen Behandlungskosten pro Arzt im gesamten Krankenhaus ermittelt werden sollen. Die Behandlungskosten ergeben sich dabei aus der Summe der von ihm während einzelner Behandlungsvorgänge verbrauchter medizinischer Artikel.

In einem ersten Schritt sind dazu für einen Arzt die Behandlungskosten per Summation zu bilden. Mit $a als Variable für den aktuell zu betrachtenden Arzt ergibt sich der Gesamtbetrag für jede Behandlung, für die dieser Arzt die Verantwortung zeichnet, durch Multiplikation von Menge (aus der Kollektion Patienten) und Einzelpreis (aus Verbrauchsartikel.xml), wobei als Verbundkriterium die Gleichheit des Artikels herangezogen wird. Eine Summation über alle Kosten pro durchgeführter Behandlung liefert dann die Gesamtkosten pro Arzt:

for $b in fn:collection("Patienten")//Patient_stationär/
Behandlung[xqb:follow-xlink(../Arzt/@xlink:href) is $a]
return
fn:sum(for $x in $b//verbrauchter_Artikel,
$y in fn:doc("Verbrauchsartikel.xml")//Artikel
where $x/@Artikel_id = $y/@ID
return $x/@Menge * $y/Einzelpreis)

Die durchschnittlichen Behandlungskosten pro tatsächlich behandelndem Arzt ergeben sich dann durch Anwendung der fn:avg()-Funktion auf die oben berechneten Behandlungskosten für jeden einzelnen Arzt. Die gesamte Anfrage ergibt sich dann zu folgendem Ausdruck:

<Behandlungskosten_nach_Arzt>
{
for $a in fn:doc("Hochwaldklinik.xml")//Arzt
return
<Arzt>
<Name>{ $a//Vorname, $a//Nachname }</Name>
<Behandlungskosten>
{ fn:avg(for $p in fn:collection("Patienten")//
Patient_stationär/
Behandlung[xqb:follow-xlink(../Arzt/@xlink:href) is $a]
return
fn:sum(for $x in $p//verbrauchter_Artikel,
$y in fn:doc("Verbrauchsartikel.xml")
//Artikel
where $x/@Artikel_id = $y/@ID
return $x/@Menge * $y/Einzelpreis)
) }
</Behandlungskosten>
</Arzt> }
</Behandlungskosten_nach_Arzt>

 

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

<< zurückvor >>