3

私はXPathとXQueryに比較的慣れていません。と呼ばれるテーブルに格納されているXMLを使用していますtblXML。XMLは、によってこのテーブルに格納されますcaseID。この例では、この値は一意です。XML自体は、というラベルの付いた列に格納されますData

あなたが行った場合、あなたはselect * from tblXML where caseID = '12345'これを見るでしょう:

caseID        data
------        ------
12345         <root><patient><diagnosis preferred_name="diagnosis" tier="1">Melanoma</diagnosis> (XML file stored as blob in database)

XMLに飛び込むとすると、次のようになります。たとえば、これは「12345」のdata列のXMLです。caseID

<root>
    <patient>
        <diagnosis preferred_name="diagnosis" tier="1">Melanoma</diagnosis>
        <month_of_birth preferred_name="month_of_birth" tier="1">02</month_of_birth>
        <day_of_birth preferred_name="day_of_birth" tier="2">01</day_of_birth>
        <year_of_birth preferred_name="year_of_birth" tier="1">1960</year_of_birth>
        <new_tumor_events>
            <month_of_nte preferred_name="month_of_nte" tier="1">12</month_of_nte>
            <day_of_nte preferred_name="day_of_nte" tier="2">30</day_of_nte>
            <year_of_nte preferred_name="year_of_nte" tier="1">1994</year_of_nte>
        </new_tumor_events>
        <follow_ups>
            <follow_up>
                <month_of_fu preferred_name="month_of_fu" tier="1">12</month_of_fu>
                <day_of_fu preferred_name="day_of_fu" tier="2">31</day_of_fu>
                <year_of_fu preferred_name="year_of_fu" tier="1">1995</year_of_fu>
            </follow_up>
            <follow_up>
                <month_of_fu preferred_name="month_of_fu" tier="1">12</month_of_fu>
                <day_of_fu preferred_name="day_of_fu" tier="2">31</day_of_fu>
                <year_of_fu preferred_name="year_of_fu" tier="1">1996</year_of_fu>
            </follow_up>
        </follow_ups>
    </patient>
</root>

目標:@Tier属性が。 であるXMLドキュメントのすべてのレベル/ノードのすべての要素のすべての値を選択しようとしています"1"。次のように、「Value」という列の独自の行に各値が出力されるようにしたいと思います。

caseID     Value
------     ------
12345      Melanoma
12345      02
12345      1960
12345      12
12345      1994
12345      12
12345      1995
12345      12
12345      1996

これが私が書き込もうとしているものに類似したSQLです:

DECLARE @tier int 
SET @tier = '1' --To search by tier explicitly via variable

    select 
        x.caseID,
    bar.value('(//*[@tier = sql:variable("@tier")])[1]','varchar(max)') as value
from tblXML as x
    CROSS APPLY data.nodes('//*:patient') AS foo(bar)
where
    x.caseID = '12345'
    and x.data.value('(//@tier)[1]', 'varchar(3)') = '1'

これは私に...

case ID        value
------         ------  
12345          Melanoma

...しかし、私が探している追加の行ではありません。

私の混乱は、[1]CROSSAPPLYステートメントのシングルトンとコンテキストノードの両方によって課せられた制約に集中していると思います。クエリが検出したTier1の最初のインスタンスだけでなく、Tier1であるドキュメント内のすべてを取得する方法がわかりません。

この例では、CROSS APPLYステートメントのコンテキストノードがpatientXMLのセクションに焦点を合わせていることを知っていますが、XMLツリーのすべてのレベルで上下両方を検索できるようにしたいと思います。//forを使用すると、ドキュメントのすべてのレベルで検索できることはわかってい@Tierますが、コンテキストノードは、検索できるドキュメントの深さをある程度制限しているようです。

XMLを深く掘り下げて(follow_upおそらく?)、上から下に検索できることを理解しています。ただし、最も深いノードはcaseIDからcaseIDに、XMLドキュメントからXMLドキュメントに変更されます。@TierCROSS APPLYステートメントを特定のXMLドキュメントの最も深いノードにワイルドカード化し、そのドキュメント内で出現するものを探して、対応する値を取得する方法はありますか?

私は、この方法が優雅さを欠き、パフォーマンスが悪いことを理解しています。これまでのところ、探している結果を提供するための明確なドキュメントを見つけることができませんでした。

よろしくお願いします。

編集:このSQLがSQLServerのテーブル値関数のコアになることを指定する必要があります。

4

4 に答える 4

2

キーを定義します。

<xsl:key name="t" match="*[@tier]" use="@tier"/>

を使用してすべての teir=1 要素を見つけます

<xsl:for-each select="key('t', '1')">
  ....
</xsl:for-each>
于 2013-02-27T16:50:21.757 に答える
1

選択したシングルトンを削除してみてください。

DECLARE @tier int 
SET @tier = '1' --To search by tier explicitly via variable
    select 
        x.caseID,
        bar.value('/string()','varchar(max)')
from tblXML as x
    CROSS APPLY data.nodes('//*[@tier = sql:variable("@tier")]') AS foo(bar)
where
    x.caseID = '12345'

selectのxpathは、一致する属性値に基づいてノードを既にフィルター処理しているため、where制約で再度実行する必要はありません。xpath述語はwhereに類似しています。

于 2013-02-27T16:42:14.687 に答える
0

これを試して:

SELECT  
    x.caseID,
    bar.value('.','varchar(max)') as value
FROM tblXML as x
    CROSS APPLY data.nodes('//*[@tier=1]') AS foo(bar)
于 2014-08-31T04:34:18.563 に答える