Sql-Server

這個帶有交叉應用的派生表如何工作?

  • July 11, 2019

我借用了一些關於如何壓縮和解壓縮診斷程式碼字元串的程式碼,以便為我的數據倉庫建構一個橋接表。它運作良好。但是,我只是不明白它是如何進行壓縮的。這是以下程式碼的 SQL Fiddle

create table dimDiagnosisGroup (dxGroupKey int, dxCodeList nvarchar(1024))
insert into dimDiagnosisGroup
values  (1,'042, 070.70, 722.10'),
       (2,'042, 070.70, 780.52, 496, 716.90, 581.9'),
       (3,'042, 070.70, 782.1, V58.69'),
       (4,'042, 070.70, 782.3, V58.69')


WITH XMLTaggedList AS (
    SELECT dxGroupKey,
       CAST('<I>' + REPLACE(dxCodeList, ', ', '</I><I>') + '</I>' AS XML)
           AS Diagnosis_Code_List
    FROM dimDiagnosisGroup
)
    SELECT dxGroupKey,
           ExtractedDiagnosisList.X.value('.', 'VARCHAR(MAX)') AS dxCodeList2
         FROM XMLTaggedList
       CROSS APPLY Diagnosis_Code_List.nodes('//I') AS ExtractedDiagnosisList(X)

我理解XMLTaggedList部分很好。我不明白的是 Cross Apply 到ExtractedDiagnosisList(X),然後是ExtractedDiagnosisList.X.value(’.’, ‘VARCHAR(MAX)’)

當我在 select 語句中將滑鼠懸停在ExtractedDiagnosisList上時,SSMS 說它是一個派生表。但是,它對我來說有點像一個函式。我不明白Diagnosis_Code.List如何獲取 .nodes(’//I’) 函式。最後,在 SQL 中, ExtractedDiagnosisList.X.value部分對我來說看起來很陌生。它看起來像 C# 等語言的語法。

您看到的是 SQL Server 中的 XQuery 實現。儘管 XQuery 使用自己的解析器並在查詢編譯階段執行自己的代數化,但結果會與查詢的 DML 部分一起組合和優化,然後組合成一個執行計劃。

SQL Server 支持五種不同的方法。 valueexistsquerynodes用於訪問和轉換數據。最後一個,modify,使用 XML DML 來修改數據。

value() 方法從 XML 實例返回一個標量值假設您有 xml:`

declare @X xml =
'<Order OrderId="42" OrderTotal="49.96">
<Customer Id="123"/>
<OrderLineItems>
<OrderLineItem>
<ArticleId>250</ArticleId>
<Quantity>3</Quantity>
<Price>9.99</Price>
</OrderLineItem>
</OrderLineItems>
</Order>’

select @X.value('/Order[1]/Customer[1]/@Id','int')`or
select @X.value('(/Order/Customer/@Id)[1]','int')

會給你第一個訂單的第一個客戶的 ID

在您的特定情況下,value(’.’) 意味著給我來自切碎元素的所有值(我稍後會談到)請記住,在使用值函式時,您正在通過 XML 移動。現在為了使它更容易,不要“移動”太多,您可以使用功能節點將 XML 分解為關係數據。它返回一個行集,其中行表示由路徑表達式標識的節點。

例子:

declare @X xml =
'<Order OrderId="42" OrderTotal="49.96">
<Customer Id="123"/>
<OrderLineItems>
<OrderLineItem>
<ArticleId>250</ArticleId>
<Quantity>3</Quantity>
<Price>9.99</Price>
</OrderLineItem>
</OrderLineItems>
</Order>'


select C.t.value('(@Id)[1]','int')
from  @X.nodes('/Order/Customer') as C(t)

當您對錶中的 XML 列使用 nodes() 方法時,您必須使用 APPLY 運算符。

例子:

declare @X as table (xmlCode varchar(1000))
insert into @X values (
'<Order OrderId="42" OrderTotal="49.96">
<Customer Id="123"/>
<OrderLineItems>
<OrderLineItem>
<ArticleId>250</ArticleId>
<Quantity>3</Quantity>
<Price>9.99</Price>
</OrderLineItem>
</OrderLineItems>
</Order>');

WITH CTE AS(
select CAST(xmlCode as XML) as X from @X
)
select C.t.value('(@Id)[1]','int')
from  CTE
CROSS APPLY X.nodes('/Order/Customer') as C(t)

我在值和節點上使用了範例,因為您僅提供了具有這兩個功能的程式碼,如果您想了解更多資訊,請訪問

希望這個簡單的例子能讓你了解如何查詢 xml 類型

引用自:https://dba.stackexchange.com/questions/177532