3

次の XML のサンプルとselect、xml をリレーションに分割するステートメントを考えると、必要なのは の 2 番目の列がselectカテゴリの序数になることです(つまり、この場合は方向に 1、色に 2)。

注: select のリテラル値「rank()」は、プレースホルダーのままです。を使っていろいろいじっていましたが、うまくいきrankませんでした。

declare @x xml
set @x = '
    <root>
        <category>
            <item value="north"/>
            <item value="south"/>
            <item value="east"/>
            <item value="west"/>
        </category>
        <category>
            <item value="red"/>
            <item value="green"/>
            <item value="blue"/>
        </category>
    </root>'

select c.value('./@value', 'varchar(10)') as "ItemValue", 
       'rank()' as "CategoryNumber"
from @x.nodes('//item') as t(c)
4

4 に答える 4

2

ジェイコブ・セバスチャンも、彼のブログ投稿で興味深いソリューションを紹介しています。

XQuery Lab 23 - 要素の値と位置の取得

ジェイコブの提案により、クエリを次のように書き直すことができます。

SELECT
    x.value('@value','VARCHAR(10)') AS 'ItemValue',        
    p.number as 'CategoryNumber'
FROM
    master..spt_values p
CROSS APPLY 
    @x.nodes('/root/category[position()=sql:column("number")]/item') n(x) 
WHERE
    p.type = 'p'

目的の出力が得られます。

ItemValue   CategoryNumber
---------   --------------
north           1
south           1
east            1
west            1
red             2
green           2
blue            2

残念ながら、position()またはfn:id()関数のようなより明白なソリューションは、a) SQL Server で動作するか、b) SQL Server でまったくサポートされていないようです:-(

お役に立てれば

マルク

于 2009-10-07T20:37:57.677 に答える
1

たぶんこのように:各カテゴリの最初の要素を取得し、それをIDとして使用します。

これ:

select c.value('./@value', 'varchar(10)') as "ItemValue", 
    c.value('../item[1]/@value', 'varchar(10)') as "CategoryNumber"
from @x.nodes('//item') as t(c)

戻り値:

Item Value | CategoryNumber
---------------------------
north      | north
south      | north
east       | north
west       | north
red        | red
green      | red
blue       | red

そしてちょうど

select c.value('./@value', 'varchar(10)') as "ItemValue", 
   RANK() OVER (ORDER BY c.value('../item[1]/@value', 'varchar(10)')) as "CategoryNumber"
from @x.nodes('//item') as t(c)

ただし、次のように返されます。

Item Value | CategoryNumber
---------------------------
north      | 1
south      | 1
east       | 1
west       | 1
red        | 5
green      | 5
blue       | 5

しかし、それはまだ一歩先を行っています。

于 2009-10-07T16:50:49.147 に答える
1

を使用して出力を生成することはできませんがposition()(なぜ??)、XPath フィルターとして使用できます。

 with numbers (n) as (
  select 1
  union all select 2
  union all select 3
  union all select 4
  union all select 5)
 select i.x.value('@value', 'varchar(10)') as [ItemValue],
    n.n as [rank]
  from numbers n
  cross apply @x.nodes('/root/category[position()=sql:column("n.n")]') as c(x)
  cross apply c.x.nodes('item') as i(x);

より高いランクには実数テーブルを使用できます。1 つのドキュメント内の非常に多数のカテゴリの場合は効率的ではありませんが、適度な数 (数十、数百) の場合は問題なく機能します。

于 2009-10-07T17:45:59.597 に答える