2012-09-26 20 views
3

我有一個包含從報表詳細信息的XML文檔:提取XML數據 - 太多的交叉應用陳述

<Statement> 
<Id /> 

<Invoices> 
    <Invoice> 
     <Id /> 
     <Date /> 
     <AmountDue /> 
     etc. 
    </Invoice> 

    <Invoice> 
     <Id /> 
     <Date /> 
     <AmountDue /> 
     etc. 
    </Invoice> 

    <Invoice> 
     <Id /> 
     <Date /> 
     <AmountDue /> 
     etc. 
    </Invoice> 
</Invoices> 

</Statement> 

也能正常工作的聲明具體細節:

SET @statementId = @xml.value('(Id)[1]', 'UNIQUEIDENTIFIER'); 

但需要一個單例,並且只返回第一個值。我需要發票的所有值,而不僅僅是第一個,所以單身人士不會工作。

我能夠得到信息使用跨應用的語句是這樣的:

SELECT 
@statementId AS STATEMENT_ID 
Id.value('.', 'uniqueidentifier') AS INVOICE_ID 
Date.value('.', 'smalldatetime') AS INVOICE_DATE 
Due.value('.', 'decimal') AS INVOICE_AMOUNT_DUE 

FROM @xml.nodes('Statement') A(S) 
cross apply S.nodes('Invoices/Invoice') B(InvoiceD) 
cross apply InvoiceD.nodes('Id') C(Id) 
cross apply InvoiceD.nodes('Date') D(Date) 
cross apply InvoiceD.nodes('AmountDue') E(Due) 

這從語句中的每個發票返回一個ID,日期和金額 - 完美。

我試圖提取所有發票細節時出現問題。我目前有七個橫申請陳述和我得到了以下信息:

「的查詢處理器用盡了內部資源,無法 生成查詢計劃這是一個罕見的事件,只有預期的 極其複雜查詢或引用非常大的 數量的表或分區請簡化查詢如果您認爲您錯誤地收到此消息,請聯繫客戶支持服務 以獲取更多信息。

我想要做的是對發票有一個交叉申請並縮小select語句中的確切字段,但除非我使用'。'。我必須讓聲明返回一個單例,並且我沒有得到我需要的所有數據。

我做了關於SELECT語句中指定一個命名空間的一些研究,但所有的示例將命名空間是一個HTTP地址,而不是在XML文檔中的一個節點,我還沒有得到任何使用返回尚這種方法。

我在尋找的結果是這樣的,但更多的發票明細:

STATEMENT_ID  INVOICE_ID  INVOICE_DATE  INVOICE_AMOUNT_DUE  ... 
Statement-1-Id Invoice-1-Id Invoice-1-Date Invoice-1-AmountDue ... 
Statement-1-Id Invoice-2-Id Invoice-2-Date Invoice-2-AmountDue ... 
Statement-1-Id Invoice-3-Id Invoice-3-Date Invoice-3-AmountDue ... 

哪裏應該何去何從?

編輯:我刪除了一些不必要的信息。獲取所有發票特定的細節是我的目標。

+0

你想要什麼樣的結果?付款和發票是XML中的兄弟姐妹,因此我很難弄清楚在一個查詢中如何返回。 XML中帶有'*'的部分有點令人困惑。數據是否在XML中用值表示了單獨的元素? –

+0

您不必執行交叉應用於value元素。您可以指定'ID'如使用'InvoiceD.value一個單值(「ID [1]」 ......' –

+0

感謝您對這些問題 - 我已經編輯我的職務更好的信息 –

回答

4
select @XML.value('(Statement/Id/text())[1]', 'uniqueidentifier') as StatementId, 
     T.N.value('(Id/text())[1]', 'uniqueidentifier') as InvoiceId, 
     T.N.value('(Date/text())[1]', 'smalldatetime') as InvoiceDate, 
     T.N.value('(AmountDue/text())[1]', 'decimal') as AmountDue 
from @XML.nodes('/Statement/Invoices/Invoice') as T(N) 

.nodes將撕碎你的XML行,每行T.N指向其自身的發票節點。在該節點上,只有一個Id節點,因此獲取指定單身人士Id[1]作品的值。

你可以使用Id[1](Id/text())[1]但後者會給你一個更有效的執行計劃。

+0

太棒了!非常感謝! 是不是它是「/ text()」使它全部返回? –

+0

@JacobDanks不,它不是。答案 –

+0

精彩,再次感謝! –