Omet navegació

4.2.2.6 - Exemple de consulta "elaborada"

Partint d’aquest XML d’exemple que representa comandes de llibres (guardeu-lo com un document anomenat comanda_llibres.xml):

<?xml version="1.0" encoding="UTF-8"?>
<petició llibreria="Fantastica SL">
<data>15-11-2011</data>
<autor>
<nom>Frédérik McCloud</nom>
<llibres>
<llibre>
<titol>Les empentes</titol>
<quantitat>2</quantitat>
</llibre>
</llibres>
</autor>
<autor>
<nom>Corsaro Levy</nom>
<llibres>
<llibre>
<titol>Marxant de la font del gat</titol>
<quantitat>2</quantitat>
</llibre>
<llibre>
<titol>Bèstia!</titol>
<quantitat>2</quantitat>
</llibre>
</llibres>
</autor>
<autor>
<nom>Marc Blairet</nom>
<llibres>
<llibre>
<titol>Tres de tres</titol>
<quantitat>3</quantitat>
</llibre>
</llibres>
</autor>
</petició>

Es vol respondre la pregunta següent: de quins autors s’han demanat tres o més llibres?

Anem a fer l'exercici a poc a poc, de manera constructiva.

Per respondre aquesta pregunta el primer que cal és separar el document en blocs d’autor i processar-ne cada un de manera diferent. Per tant, es defineix un bucle amb un for per cada autor i s’escriu el nom per pantalla

for $autor in doc("/db/Tema9/comanda_llibres.xml")//autor
return $autor/nom

El resultat serà una llista de tots els autors:

<nom>Frédérik McCloud</nom>
<nom>Corsaro Levy</nom>
<nom>Marc Blairet</nom>

Es vol definir una restricció amb la quantitat de llibres que s’han demanat de cada autor; per tant, ho podríem intentar fer amb el where

for $autor in doc("/db/Tema9/comanda_llibres.xml")//autor
where $autor/llibres/llibre/quantitat >= 3
return $autor/nom

Aquesta és la llista dels autors que tenen alguna petició de 3 o més llibres

<nom>Marc Blairet</nom>

Però es pot veure que encara no és el demanat, ja que no apareix l’autor Corsaro Levy, del qual s’han demanat dues unitats llibres diferents. Per tant, agrupem les quantitats per obtenir el resultat correcte

for $autor in doc("/db/Tema9/comanda_llibres.xml")//autor
where sum($autor/llibres/llibre/quantitat) >= 3
return $autor/nom

Ara el resultat sí que és el correcte:

<nom>Corsaro Levy</nom>
<nom>Marc Blairet</nom>

Podem fer que el resultat siga més “bonic” mostrant les quantitats venudes al costat de cada autor i ordenant de més a menys els resultats.

for $autor in doc("/db/Tema9/comanda_llibres.xml")//autor 
let $suma := sum($autor/llibres/llibre/quantitat)
where $suma >=3
order by $suma descending
return concat($autor/nom," : ", $suma)

Es pot veure que per no haver d’escriure diverses vegades l’expressió de suma s’ha definit una variable $suma i d’aquesta manera l’expressió ha quedat més fàcil d’escriure

"Corsaro Levy : 4"
"Marc Blairet : 3"

La funció concat() ha eliminat les etiquetes XML i ha generat un resultat de text. Si es vol mantenir una estructura XML es pot crear manualment amb l’ajuda de les expressions avaluables:

for $autor in doc("/db/Tema9/comanda_llibres.xml")//autor 
let $suma := sum($autor/llibres/llibre/quantitat)
where $suma >=3
order by $suma descending
return <autor> { concat($autor/nom," : ", $suma) } </autor>

Que generarà:

<autor>Corsaro Levy : 4</autor>
<autor>Marc Blairet : 3</autor>