0

环境:SQL Server 2012。主要和次要(值)索引建立在 xml 列上。

假设我有一个带有 xml 列 WordIndex 的表 Message。我还有一个包含 WordId 和 WordText 的表格 Word。Message.WordIndex 的 XML 具有以下架构:

<xs:schema attributeFormDefault="unqualified"
           elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.example.com">
    <xs:element name="wi">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="w">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element maxOccurs="unbounded" name="p" type="xs:unsignedByte" />
                        </xs:sequence>
                        <xs:attribute name="wid" type="xs:unsignedByte" use="required" />
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

以及一些与之相关的数据:

<wi xmlns="http://www.example.com">
  <w wid="1">
    <p>28</p>
    <p>72</p>
    <p>125</p>
  </w>
  <w wid="4">
    <p>89</p>
  </w>
  <w wid="5">
    <p>11</p>
  </w>
</wi>

我需要使用 OR 或 AND 在我的 xml 列 WordIndex 中搜索多个值。我所做的是相当初级的,因为我是 XQuery 中的 n00b(取自调试输出,因此是真实值):

with xmlnamespaces(default 'http://www.example.com')
select
    m.Subject,
    m.MessageId,
    m.WordIndex.query('
        let $dummy := 0
        return
            <word_list>
            {
                for $w in /wi/w
                    where $w/@wid=64
                    return <word wid="64" pos="{data($w/p)}"/>
            }
            {
                for $w in /wi/w
                    where $w/@wid=70
                    return <word wid="70" pos="{data($w/p)}"/>
            }
            {
                for $w in /wi/w
                    where $w/@wid=63
                    return <word wid="63" pos="{data($w/p)}"/>
            }
            </word_list>
        ') as WordPosition
from
    Message as m
-- more joins go here ...
where
    -- more conditions go here ...
    and m.WordIndex.exist('/wi/w[@wid=64]') = 1
    and m.WordIndex.exist('/wi/w[@wid=70]') = 1
    and m.WordIndex.exist('/wi/w[@wid=63]') = 1

如何优化?

4

1 回答 1

0

不确定我是否理解您的预期结果,但您可以使其更加通用和数据驱动(例如使用 sql:column 或 sql:variable)。尝试这样的事情:

declare @wids table ( wid INT PRIMARY KEY )

insert into @wids ( wid )
values ( 64 ), ( 70 ) 

;with xmlnamespaces(default 'http://www.example.com') 
select 
    m.Subject, 
    m.MessageId, 
    m.WordIndex.query(' 
        return 
            <word_list> 
            { 
                for $w in /wi/w
                where $w/@wid = sql:column("w.wid")
                return <word wid="{$w/@wid}" pos="{data($w/p)}"/> 
            } 
            </word_list> 
        ') as WordPosition 
from 
    Message as m
    cross apply @wids w 
where m.WordIndex.exist('wi/w[@wid=sql:column("w.wid")]') = 1
于 2012-09-09T21:35:52.680 回答