xQuery から 2 つのドキュメントを開いて結合することはできますか?
3 に答える
「複数のソースからのデータを1つの結果に結合する結合は、非常に重要なタイプのクエリです。このセクションでは、XQueryでいくつかのタイプの結合を表現する方法を説明します。次の3つのドキュメントに基づいて例を示します。
parts.xml
多くのpart
要素を含む名前の付いたドキュメント。各要素には、サブ要素part
が含まれています。partno
description
suppliers.xml
多くのsupplier
要素を含む名前の付いたドキュメント。各要素には、サブ要素supplier
が含まれています。suppno
suppname
catalog.xml
サプライヤと部品の関係に関する情報を含む名前のドキュメント。カタログドキュメントには多くのitem
要素が含まれており、各要素には、、、およびサブ要素が含まれてpartno
いsuppno
ますprice
。
従来の(「内部」)結合は、3つのドキュメントからの情報を組み合わせた次の例に示すように、2つ以上の関連するソースからの情報を返します。この例では、カタログドキュメントから派生した「説明カタログ」が生成されますが、部品番号の代わりに部品の説明が含まれ、サプライヤ番号の代わりにサプライヤ名が含まれています。新しいカタログは、部品の説明のアルファベット順に、次にサプライヤー名の順に並べられています。*
<descriptive-catalog>
{
for $i in fn:doc("catalog.xml")/items/item,
$p in fn:doc("parts.xml")/parts/part[partno = $i/partno],
$s in fn:doc("suppliers.xml")/suppliers
/supplier[suppno = $i/suppno]
order by $p/description, $s/suppname
return
<item>
{
$p/description,
$s/suppname,
$i/price
}
</item>
}
</descriptive-catalog>
前のクエリは、サプライヤがある部品と部品があるサプライヤに関する情報のみを返します。外部結合は、他のソースに一致する要素がない要素を含む、参加している1つ以上のソースからの情報を保持する結合です。たとえば、サプライヤと部品の間の左外側の結合は、一致する部品がないサプライヤに関する情報を返す場合があります。」
XQueryには標準のdocument()関数(XSLT関数)がなく、代わりに「 XQuery1.0およびXPath2.0の関数と演算子」の一部であるdoc()関数があることに注意してください。
クリスの答えには少なくとも2つの誤りがあります:
- XQueryでは大文字と小文字が区別されます。Chrisの例で使用されている大文字のキーワードは、準拠するXQueryプロセッサでは許可されません。
- doc()のような標準関数に接頭辞を付ける必要はありません。接頭辞が付いているXQuery仕様を引用しているだけです。それ以外の場合、私自身のコードでは、「
fn
」プレフィックスを省略します。 - 関数document()は、標準のXQuery/XPath関数ではありません。代わりにdoc()関数を使用する必要があります。
それよりも簡単です(少なくともSAXONを使用):
let $items := (
doc("file1.xml") ,
doc("file2.xml") ,
doc("file3.xml")
)
for $x in $items ...
XQueryで、次のように記述した場合:
for $x in doc('doc1.xml')//a
for $y in doc('doc2.xml')//a
where $x/@name = $y/@name
return $x
次に、XQueryプロセッサは、これが結合であることを検出するのに十分スマートである必要があります。
XQueryで、何かが結合であることを明示的に指定することはありません。XQueryの一般的なテーマは、プログラムが必要な情報を言うことであり、それを計算する方法ではありません。
実際には2番目のドキュメントを繰り返しループしているように見えるかもしれませんが、実際のXQueryプロセッサはこれをよりインテリジェントに実行し、次のSQLステートメントにほぼ類似しています(私のSQLは非常に錆びているので、この構文が完全に間違っている場合はお詫びします)
SELECT doc1.a
FROM doc1 INNER JOIN doc2
WHERE doc1.name = doc2.name
XMarkベンチマークにはいくつかのサンプルクエリが含まれていますが、これらは一見の価値があります。特にクエリ9から12は結合を実行します。