Учебное пособие (1075724), страница 22
Текст из файла (страница 22)
FLWOR – For, Let, Where, Order by, Return.FOR – создание связанных переменных как переменных циклаLET – создание одиночных связанных переменныхWHERE – условиеORDER BY – порядок сортировкиRETURN – возвращаемое значениеТаблица 4.10. Примеры запросов. Простой пример выражения FLWOR.for $i in (1 to 3)<number><i>1</i> <i2>2</i2>let $i2:= $i + 1</number>return<number><i>2</i> <i2>3</i2><number><i>{$i}</i><i2>{$i2}</i2></number><number><i>3</i> <i2>4</i2></number></number>Выражения FOR и LET генерируют упорядоченную последовательностькортежей связанных переменных (tuples of bound variables), которая называетсяпотоком кортежей (tuple stream).Поток кортежей фильтруется в соответствии с условием WHERE.205Поток кортежей сортируется в соответствии с ORDER BY.Выражение RETURN выполняется для каждого кортежа в потоке кортежей.Таблица 4.11.
Примеры запросов. Примеры на выражение FLWOR.for $i in (1 to 5)<number i1="1" i2="2" i3="3"/><number i1="2" i2="4" i3="6"/>let $i2:= $i * 2,<number i1="3" i2="6" i3="9"/>$i3:= $i * 3<number i1="4" i2="8" i3="12"/>returnПример потокакортежей<number i1="5" i2="10" i3="15"/><number i1="{$i}"i2="{$i2}"i3="{$i3}" />for $i in (1 to 5)let $i2:= $i * 2,<number i1="1" i2="2" i3="3"/><number i1="3" i2="6" i3="9"/><number i1="5" i2="10" i3="15"/>Условиевыбирает$i3:= $i * 3толькоwhere $i mod 2 != 0нечетныеreturnэлементы<number i1="{$i}"i2="{$i2}"i3="{$i3}" />for $i in (1 to 5)let $i2:= $i * 2,$i3:= $i * 3<number i1="5" i2="10" i3="15"/><number i1="3" i2="6" i3="9"/><number i1="1" i2="2" i3="3"/>Сортировкавпорядкеубыванияwhere $i mod 2 != 0order by $idescendingreturn<number i1="{$i}"i2="{$i2}"i3="{$i3}" />206let $doc :=<elements><number i1="1" i2="2" i3="3"/><number i1="2" i2="4" i3="6"/><number i1="3" i2="6" i3="9"/>Переборэлементовдокумента<e>1</e><e>2</e><e>3</e></elements>for $i in $doc/elet $i2:= $i * 2,$i3:= $i * 3return<number i1="{$i}"i2="{$i2}"i3="{$i3}" />Дополнительные примеры:Таблица 4.12.
Примеры запросов. Дополнительные примеры на выражение FLWOR.let $i:= (1 to 3)<rez>1 2 3</rez>операторами FOR иreturn <rez>{$i}</rez>for $i in (1 to 3)Различие между<rez>1</rez>LET<rez>2</rez>return <rez>{$i}</rez><rez>3</rez>for<rez i="1" j="1"/>Использование<rez i="1" j="2"/>нескольких$i in (1 to 3),$j in (1 to 3)return <rez i="{$i}"j="{$j}" /><rez i="1" j="3"/><rez i="2" j="1"/>переменных в FOR.<rez i="2" j="2"/>Декартово<rez i="2" j="3"/>произведение.<rez i="3" j="1"/><rez i="3" j="2"/><rez i="3" j="3"/>let $i as xs:decimal :=1<rez i="1"/>Возможнозадание207return <rez i="{$i}"/>типапеременнойспомощьюконструкции«as тип»Возможно задание в FOR позиционной переменной с помощью ключевогослова «at».
Позиционная переменная всегда типа xs:integer. Она указываетпозицию, в которой находится элемент.Таблица 4.13. Примеры запросов. Использование «at».for $i at $pos in ("A",<rez i="A" pos="1"/>Позиционная"B", "C")<rez i="B" pos="2"/>переменная<rez i="C" pos="3"/>return <rez i="{$i}"pos="{$pos}"/>Выражений FOR и LET может быть несколько в одном запросе. Они могутследовать в произвольном порядке.При совместном использовании нескольких FOR и LET генерируется потоккортежей для переменных всех уровней.Таблица 4.14. Примеры запросов.
Совместное использование FOR и LET.let $i1:=1, $i2:=3for $i in ($i1 to $i2)let $i3 := $i*2return <rez i="{$i}"i3="{$i3}" i1="{$i1}"<rez i="1" i3="2" i1="1"Использованиеi2="3"/>нескольких FOR<rez i="2" i3="4" i1="1"i2="3"/><rez i="3" i3="6" i1="1"и LET в одномзапросеi2="3"/>i2="{$i2}"/>for $j in 1 to 3let $i1:=1, $i2:=$jfor $i in ($i1 to $i2)<rez j="1" i="1" i3="2"i1="1" i2="1"/><rez j="2" i="1" i3="2"i1="1" i2="2"/>208let $i3 := $i*2return <rez j="{$j}"i="{$i}" i3="{$i3}"i1="{$i1}" i2="{$i2}"/><rez j="2" i="2" i3="4"i1="1" i2="2"/><rez j="3" i="1" i3="2"i1="1" i2="3"/><rez j="3" i="2" i3="4"i1="1" i2="3"/><rez j="3" i="3" i3="6"i1="1" i2="3"/>for $i in 1 to 3let $i:=$i*2<rez i="2"/>Возможно<rez i="4"/>переопределение<rez i="6"/>return <rez i="{$i}"/>именипеременнойЗначение выражения WHERE вычисляется для каждого кортежа в потокекортежей.
Если значение = false, то кортеж удаляется.В случае использования нескольких переменных в FOR условие WHEREможет быть использовано для связи между ними (join).Таблица 4.15. Примеры запросов. Использование WHERE.for $i in (1 to 3),$j in (1 to 3)<rez i="2" j="2"/>Для чисел<rez i="3" j="3"/>where $i=$j and $i > 1return <rez i="{$i}"j="{$j}" />let $doc1 :=<rez>Для<elements><e<e id="1">1</e>элементов.id="1">1</e><eid="2">2</e><eid="3">3</e></elements>,$doc2 := <values><vid1="1" value="value1"/><v id1="2"value="value2"/><v id1="1" value="value1"/></rez><rez>Безфильтра.<e id="1">1</e><v id1="2" value="value2"/></rez><rez><e id="2">2</e><v id1="1" value="value1"/>209</values></rez><rez>for $i in $doc1/e, $j in<e id="2">2</e>$doc2/v<v id1="2" value="value2"/></rez>return<rez><rez>{$i}{$j}</rez><e id="3">3</e><v id1="1" value="value1"/></rez><rez><e id="3">3</e><v id1="2" value="value2"/></rez>let $doc1 :=<rez>Для<elements><e<e id="1">1</e>элементов.<v id1="1" value="value1"/>id="1">1</e><eС</rez>id="2">2</e><eфильтром.<rez>id="3">3</e></elements>,<e id="2">2</e><v id1="2" value="value2"/>$doc2 := <values><v</rez>id1="1" value="value1"/><v id1="2"value="value2"/></values>for $i in $doc1/e, $j in$doc2/vwhere $i/@id=$j/@id1return<rez>{$i}{$j}</rez>Сортировка с использованием ORDER BY:Таблица 4.16.
Примеры запросов. Использование ORDER BY.let $doc :=<elements><e>1</e><e>2</e><e/></elements><e/><e>1</e><e>2</e>Сортировкаповозрастанию210for $i in $doc/eorder by $i ascendingreturn $ilet $doc :=<elements><e>1</e><e>2</e><e/> </elements><e>2</e><e>1</e><e/>Сортировкапо убываниюfor $i in $doc/eorder by $i descendingreturn $ilet $doc :=<elements><e>1</e><e>2</e><e/></elements>for $i in $doc/e<e/><e>1</e><e>2</e>Примерempty.Ожидаемый результат:<e>1</e>order by $i ascending empty<e>2</e>greatest<e/>return $iВыражения empty greatest (пустые значения считаются большими) и emptyleast (считаются меньшими) вероятнее всего не работают в текущей версии eXist.4.3.9 Соединение документов с помощью выражения FLWORЗадача связи (join) между двумя документами может быть решена тремяспособами. с помощью for с помощью let с помощью whereВ примере используются файлы «doc1.xml» и «doc2.xml» следующейструктуры:<result>211<rez><doc><e>1</e><e>1</e>...<e>500</e></doc></rez></result>В файле «doc_rev.xml» элементы расположены в обратном порядке.Для создания тестового примера может быть использован следующий запрос:let $doc := <doc>{for $i in fn:reverse(1 to 500)return <e>{$i}</e>}</doc>,$file := doc("/db/Examples/doc_rev.xml")returnupdate insert $doc into $file//rezПримеры соединения:Таблица 4.17.
Примеры запросов. Соединение документов.let $doc1 :=Связывание с помощью where.doc("/db/Examples/doc1.xml"),Время выполнения = 8.7 сек.$doc2 :=doc("/db/Examples/doc2.xml")Если вместо doc2.xml использоватьfor $i in $doc1//e, $j inфайл$doc2//eвыполнения почти не меняется.doc_rev.xml,товремяwhere $i=$jreturn <p>{$i}{$j}</p>212let $doc1 :=Связывание с помощью let.doc("/db/Examples/doc1.xml"),Время выполнения = 5.8 сек.$doc2 :=doc("/db/Examples/doc2.xml")Если вместо doc2.xml использоватьfor $i in $doc1//eфайлlet $j:=$doc2//e[.=$i]выполнения почти не меняется.doc_rev.xml,товремяreturn <p>{$i}{$j}</p>let $doc1 :=Связывание с помощью for.doc("/db/Examples/doc1.xml"),Время выполнения = 5.8 сек.$doc2 :=doc("/db/Examples/doc2.xml")Если вместо doc2.xml использоватьfor $i in $doc1//e,файл$j in $doc2//e[.=$i]выполнения почти не меняется.doc_rev.xml,товремяreturn <p>{$i}{$j}</p>Если элементы в разных документах расположены в обратном порядке, то наскорость выполнения запроса это почти не влияет.В данном примере показано, что в eXist соединение с помощью whereмедленнее, чем с помощью let или for.
Но на это может влиять много факторов –наличие индексов, и т.д. В другой XML-ориентированной СУБД, наоборот,соединение с помощью where может быть быстрее.4.3.10 Условное выражение if-then-elseТаблица 4.18. Примеры запросов. Условное выражение.if (1=1)then <rez>1</rez>else <rez>2</rez><rez>1</rez>Выражениеможетиспользоватьсяотдельно иливнутри FLWOR213let $doc :=<elements><e>1</e><e>2</e><e>1</e><e>2</e><e>333</e>Использованиеif внутри let<e>3</e></elements>for $i in $doc/elet $j := ( if ($i=3) then<e>333</e> else $i )return $jlet $doc :=<elements><e>1</e><e>2</e><e>1</e><e>2</e><e>333</e>Использованиеif внутри return<e>3</e></elements>for $i in $doc/ereturnif ($i=3) then <e>333</e> else $ilet $doc :=<elements><e>1</e><e>2</e><e>3</e></elements><e>1</e><e>333</e><e>333</e>Использованиеor, and ифункции fn:notfor $i in $doc/e returnif (($i=2 or $i=3) andfn:not($i=1)) then <e>333</e>else $i4.3.11 Выражения some и everyВыражения some и every в спецификации также называются QuantifiedExpressions.














