@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

SQL Server 2005 の XQuery で OUTER JOIN

1
投稿者投稿内容
ふナぷぅ
会議室デビュー日: 2004/06/30
投稿数: 4
投稿日時: 2008-10-15 21:16
はじめまして。

現在、SQL Server 2005のXMLの機能を使って以下のようなバッチを作っています。

1.毎日テーブルからデータをXMLとして抽出し、ファイルに保存する。
2.当日分のXMLファイルと前日分のXMLファイルを比較して、変更点がわかるようにHTMLに表示する。

1の機能はFOR XMLを使用して実装できましたが、
2の機能のうち、当日分のXMLと前日分のXMLを比較する機能の実装ができません。

2の比較機能実装の手段として、以下のような処理を行っています。

(1)2つのXMLファイルを2つのテーブルのXML型の列にロードする。
(2)XML型の列からXQueryを使って列を抽出して、XMLのノード名を変えてUNION、変数に格納する。
(3)変数からXQueryを使って当日分、前日分を1つのノードにまとめ、XMLファイルとして出力する。
(4)XSLで前日分、当日分を比較できるよう、HTMLに出力する。

具体的なデータの流れで言うと、
(1)で元となるXML
・前日分
<名簿 No="1" 名前="太郎">
<住所 都道府県="東京都"/>
<電話 優先順位="1" 番号="03xxxxxxxx"/>
<電話 優先順位="2" 番号="090xxxxxxx"/>
</名簿>
<名簿 No="2" 名前="次郎">
<住所 都道府県="大阪府"/>
<電話 優先順位="1" 番号="03xxxxxxxx"/>
<電話 優先順位="2" 番号="090xxxxxxx"/>
</名簿>

・当日分
<名簿 No="1" 名前="太郎">
<住所 都道府県="東京都"/>
<電話 優先順位="1" 番号="03xxxxxxxx"/>
<電話 優先順位="2" 番号="090xxxxxxx"/>
</名簿>
<名簿 No="2" 名前="次郎">
<住所 都道府県="大阪府"/>
<電話 優先順位="1" 番号="03xxxxxxxx"/>
</名簿>
<名簿 No="3" 名前="三郎">
<住所 都道府県="京都府"/>
<電話 優先順位="1" 番号="03xxxxxxxx"/>
<電話 優先順位="2" 番号="090xxxxxxx"/>
</名簿>

(2)で作成したXML
<当日分名簿 No="1" 当日分名前="太郎">
<当日分住所 当日分都道府県="東京都"/>
<当日分電話 当日分優先順位="1" 当日分番号="03xxxxxxxx"/>
<当日分電話 当日分優先順位="2" 当日分番号="090xxxxxxx"/>
</当日分名簿>
<当日分名簿 No="2" 当日分名前="次郎">
<当日分住所 当日分都道府県="大阪府"/>
<当日分電話 当日分優先順位="1" 当日分番号="03xxxxxxxx"/>
</当日分名簿>
<当日分名簿 No="3" 当日分名前="三郎">
<当日分住所 当日分都道府県="京都府"/>
<当日分電話 当日分優先順位="1" 当日分番号="03xxxxxxxx"/>
<当日分電話 当日分優先順位="2" 当日分番号="090xxxxxxx"/>
</当日分名簿>
<前日分名簿 No="1" 前日分名前="太郎">
<前日分住所 前日分都道府県="東京都"/>
<前日分電話 前日分優先順位="1" 前日分番号="03xxxxxxxx"/>
<前日分電話 前日分優先順位="2" 前日分番号="090xxxxxxx"/>
</前日分名簿>
<前日分名簿 No="2" 前日分名前="次郎">
<前日分住所 前日分都道府県="大阪府"/>
<前日分電話 前日分優先順位="1" 前日分番号="03xxxxxxxx"/>
<前日分電話 前日分優先順位="2" 前日分番号="090xxxxxxx"/>
</前日分名簿>

Noが主キーとなっているので、Noだけ前日分、当日分という接頭語はつけないで変換しています。
・・・ここまではうまくいっています。
問題はこの次です。

(3)で実行しているXQuery
SELECT @x.query('
for $t in //当日分名簿
return
for $y in //前日分名簿
where $y/@No=$t/@No
return
element 名簿{
attribute No{$t/@No},
attribute 当日分名前{$t/@当日分名前},
attribute 前日分名前{$y/@前日分名前},
for $tj in $t/当日分住所
return
for $yj in $y/前日分住所
return
element 住所{
attribute 当日分都道府県{$tj/@当日分都道府県},
attribute 前日分都道府県{$yj/@前日分都道府県},
},
for $td in $t/当日分電話
return
for $yd in $y/前日分電話
where $td/@当日分優先順位=$yd/@前日分優先順位
return
element 電話{
attribute 当日分優先順位{$td/@当日分優先順位},
attribute 前日分優先順位{$yd/@前日分優先順位},
attribute 当日分番号{$td/@当日分番号},
attribute 前日分番号{$yd/@前日分番号}
}
}
') as Result
;

このXQueryを実行して、以下のような結果を得たいのです。
(いわゆる、FULL OUTER JOINをしたいのです。)

<名簿 No="1" 当日分名前="太郎" 前日分名前="太郎">
<住所 当日分都道府県="東京都"/ 前日分都道府県="東京都">
<電話 当日分優先順位="1" 前日分優先順位="1" 当日分番号="03xxxxxxxx" 前日分番号="03xxxxxxxx"/>
<電話 当日分優先順位="2" 前日分優先順位="2" 当日分番号="090xxxxxxx" 前日分番号="090xxxxxxx"/>
</名簿>
<名簿 No="2" 当日分名前="次郎" 前日分名前="次郎">
<住所 当日分都道府県="大阪府" 前日分都道府県="大阪府" 前日分番号="03xxxxxxxx"/>
<電話 当日分優先順位="1" 前日分優先順位="1" 当日分番号="03xxxxxxxx"/>
<電話 前日分優先順位="2" 前日分番号="090xxxxxxx"/>
</名簿>
<名簿 No="3" 当日分名前="三郎">
<住所 当日分都道府県="京都府"/>
<電話 当日分優先順位="1" 当日分番号="03xxxxxxxx"/>
<電話 当日分優先順位="2" 当日分番号="090xxxxxxx"/>
</名簿>

しかし、実際にやってみると以下のような結果にしかなりません。
(INNER JOINのような結果になっていしまいます。)

<名簿 No="1" 当日分名前="太郎" 前日分名前="太郎">
<住所 当日分都道府県="東京都"/ 前日分都道府県="東京都">
<電話 当日分優先順位="1" 前日分優先順位="1" 当日分番号="03xxxxxxxx" 前日分番号="03xxxxxxxx"/>
<電話 当日分優先順位="2" 前日分優先順位="2" 当日分番号="090xxxxxxx" 前日分番号="090xxxxxxx"/>
</名簿>
<名簿 No="2" 当日分名前="次郎" 前日分名前="次郎">
<住所 当日分都道府県="大阪府" 前日分都道府県="大阪府" 前日分番号="03xxxxxxxx"/>
<電話 当日分優先順位="1" 前日分優先順位="1" 当日分番号="03xxxxxxxx"/>
</名簿>

(3)で実行しているXQueryの記述はW3CのXQuery 1.0 2006年06月勧告に記載
(日本語訳:http://t.kunishi.googlepages.com/xquery.html)されているLEFT JOINの記述を倣ったため、
FULL JOINとは行かないと思いますが、せめてLEFT JOINになってNo.3のノードが出力されることを期待していました。

長文になりましたが、同じ形式のXML文書をあるキーでOUTER JOINして1つのノードにまとめる方法をご教授いただければと思います。

※別の会議室にも投稿しましたが、範囲が重複すると思い、こちらにも投稿させていただきました。
ふナぷぅ
会議室デビュー日: 2004/06/30
投稿数: 4
投稿日時: 2008-10-20 11:23
解決しました。

私の私用の解釈の誤りでした。
どうやら、return句のところは、カンマが入るたびにfor句の参照が切れるようで、
この場合、LEFT JOINしたい項目1件ごとにfor〜returnを記述する必要があるようです。

詳しくは契約の関係上記載できません。ご了承ください。

ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)