この問題を示しているのは、nodes ステートメントが 2 回リストされているクロス適用です。クロス適用でノードに依存するのではなく、拡張機能から直接xmlにあるものを表示するために、代わりに「クエリ」拡張機能を使用して「ノード」構文で行っていることを実行します。問題は、その ID を取得した視聴者に表示していないことですか? 実行時に xml 自体から判断しているのか、それとも別のテーブルに結合しているのか、xml の別の部分が存在しないのかを判断していますか? 本質的にノードで起こっていることは、それが相互に適用され、「そのノード階層に 2 つの値があります」と言っているということです。次に、別のノードを再度クロス適用すると、同じものが 2 回返されます。クロス適用を正確に 2 回使用する場合は注意が必要です。差別化を示すことはできますが、あなたが 1 に戻っていることをどのように知ることができませんか (訪問者の後に int を探しているだけですか?) あなたが望んでいるものを正確に表現する方法がわかりません.
編集:さて、それは私がその時思ったことです。現在、私のコードは他のコードよりも長くなる可能性があります。これを行う簡単な方法があることは認めますが、次の 3 つのことを行います。
- ノードは、信頼する必要がある行を繰り返すという点で便利であるため、ノードを使用して相互適用を維持してください。ただし、ノードに使用する名前に人為的なフラグを追加します。次に、ノードを使用して 2 つの select ステートメントを結合します。
- 次に、ネストされた select を from ステートメントとして使用し、設定したフラグに基づいてウィンドウ関数で行番号を決定します。
- 次に、それを再度ネストし、行番号の Id とまったく同じ行番号を使用してから、任意に設定したフラグに基づいて max(case when) に基づいて構文ピボットを実行します。
私は通常、cte を好みますが、あなたの XML 名前空間には「with」の始まりがあり、最初の cte も同様であるため、構文がそれを回避する方法を忘れていました。ネストされた選択 IMHO は、複数あると毛むくじゃらになる可能性があるため、通常は CTE を選択しますが、この場合、別のネストされた選択の内部でネストされた選択を行いました。これが役立つことを願っています:
declare @xml xml = '<upx:Root xmlns:upx="http://www.w3.org/2001/XMLSchema">
<upx:Visitors>
<upx:Visitor>Visitor1</upx:Visitor>
<upx:Visitor>Visitor2</upx:Visitor>
</upx:Visitors>
<upx:Senders>
<upx:Sender>Sender1</upx:Sender>
</upx:Senders>
</upx:Root>'
;
declare @Xmltable table ( xmlDocument xml);
insert into @XmlTable values (@xml);
WITH XMLNAMESPACES (default 'http://www.w3.org/2001/XMLSchema')
select
pos as Id
, max(case when Listing = 'Visitors' then Value end) as Visitors
, max(case when Listing = 'Senders' then Value end) as Senders
from
(
select
*
, row_number() over(partition by Listing order by Value) as pos
from
(
SELECT
'Visitors' as Listing
, a.value('.', 'NVARCHAR(50)') AS Value
FROM @XmlTable AS X
CROSS APPLY xmlDocument.nodes('Root/Visitors/Visitor') AS aa(a)
union
SELECT
'Senders'
, b.value('distinct-values(.)', 'NVARCHAR(50)') AS Sender
FROM @XmlTable AS X
CROSS APPLY xmlDocument.nodes('Root/Senders/Sender') AS bb(b)
) as u
) as listing
group by pos