CTEとXML句をaと結合するにはどうすればよいですか?
-
09-10-2019 - |
質問
さまざまなレベルのネストを備えたいくつかのXMLを生成しようとしていますが、単純化が過剰に分解されるリスクがあるため、出力XMLはフォーマットの大まかになります。
<invoice number="1">
<charge code="foo" rate="123.00">
<surcharge amount="10%" />
</charge>
<charge code="bar" />
</invoice>
私がこのために継承したデータベーススキーマは、異なるテーブルに格納されているチャージがあります。つまり、料金の出身地からのテーブルに基づいて、追加の貯蔵が異なることを意味します。
あなたを考えると 使えない UNION
sと FOR XML
, 、私はいくつかやった UNION
cteで、次の線に沿って何か
WITH Charges ( [@code], [@rate], surcharge, InvoiceId ) AS (
SELECT code AS [@Code], amount AS [@rate], NULL as surcharge, InvoiceId
FROM item.charges
UNION ALL
SELECT
code AS [@Code],
amount AS [@rate],
(
SELECT amount AS [@amount]
FROM order.surcharges os
WHERE oc.ChargeId = os.ChargeId
FOR XML PATH('surcharge'), TYPE
),
InvoiceId
FROM order.charges oc
)
SELECT
Number AS [@number],
(
SELECT
[@code],
[@rate],
surcharge
FROM Charges
WHERE Charges.InvoiceId = i.InvoiceId
)
FROM Invoices i
FOR XML PATH( 'invoice' ), TYPE
今、それは 信じられないほど 近く、与える(ネストされたものに注意してください <surcharge>
):
<invoice number="1">
<charge code="foo" rate="123.00">
<surcharge>
<surcharge amount="10%" />
</surcharge>
</charge>
<charge code="bar" />
</invoice>
しかし、新しい要素としてではなく、要素の内容として扱われるXML列の値を含めるように終了クエリを取得する方法を見つける必要があります。これは可能ですか、それとも新しいアプローチを取る必要がありますか?
解決 2
(偽の)列を「*」と命名すると、その列のコンテンツが要素のコンテンツとして使用されるため、以下のSQLを変更すると機能します。
WITH Charges ( [@code], [@rate], surcharge, InvoiceId ) AS (
SELECT code AS [@Code], amount AS [@rate], NULL as surcharge, InvoiceId
FROM item.charges
UNION ALL
SELECT
code AS [@Code],
amount AS [@rate],
(
SELECT amount AS [@amount]
FROM order.surcharges os
WHERE oc.ChargeId = os.ChargeId
FOR XML PATH('surcharge'), TYPE
),
InvoiceId
FROM order.charges oc
)
SELECT
Number AS [@number],
(
SELECT
[@code],
[@rate],
surcharge AS [*] -- Thsi will embed the contents of the previously generated XML in here.
FROM Charges
WHERE Charges.InvoiceId = i.InvoiceId
)
FROM Invoices i
FOR XML PATH( 'invoice' ), TYPE
他のヒント
Mulitpleの行(@Charge、@Rate、およびXMLタイプを返す列クエリがあります。
サブクエリが存在しない場合、選択リストで1つの式のみを指定できます。
ただし、クエリをに移動することで簡単に修正されます outer apply
. 。ダブルを削除します surcharge
要素、次のようにXML列名をできるだけ下に移動できます。
;WITH Charges (code, rate, surcharge, InvoiceId) AS
(
SELECT code, amount, NULL, InvoiceId
FROM @charges
UNION ALL
SELECT code
, amount
, (
SELECT amount AS [@amount]
FROM @surcharges os
WHERE oc.ChargeId = os.ChargeId
FOR XML PATH('surcharge'), TYPE
)
, InvoiceId
FROM @charges oc
)
SELECT Number AS [@number]
, c.code as [charge/@code]
, c.rate as [charge/@rate]
, c.surcharge as [charge]
FROM @Invoices i
outer apply
(
SELECT code
, rate
, surcharge
FROM Charges
WHERE Charges.InvoiceId = i.InvoiceId
) c
WHERE i.InvoiceID = 1
FOR XML PATH( 'invoice' ), TYPE
たとえば、これは印刷されます。
<invoice number="1">
<charge code="1" rate="1" />
</invoice>
<invoice number="1">
<charge code="1" rate="1">
<surcharge amount="1" />
</charge>
</invoice>
最初の要素は、組合の上部から来ています。 surcharge = null
.
「for xml path( 'surcharge')」ステートメントでルートノードタイプを省略することで、これを行うことができると思います。つまり、代わりに「XML Path( '')」を使用します。