Ant*_*ese 6 sql-server cte functions cross-apply
我借用了一些关于如何压缩和解压缩诊断代码字符串的代码,以便为我的数据仓库构建桥表。它运作良好。但是,我只是不明白它是如何进行解压缩的。这是以下代码的 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)
Run Code Online (Sandbox Code Playgroud)
我理解XMLTaggedList部分很好。我不明白的是交叉应用到ExtractedDiagnosisList(X),然后是ExtractedDiagnosisList.X.value('.', 'VARCHAR(MAX)')。
当我将鼠标悬停在 select 语句中的ExtractedDiagnosisList 上时,SSMS 说它是一个派生表。然而,它对我来说有点像一个函数。我不明白Diagnosis_Code.List如何获得 .nodes('//I') 函数。最后,在 SQL 中,ExtractedDiagnosisList.X.value部分对我来说看起来很陌生。它看起来像是来自 C# 等语言的语法。
小智 7
您看到的是 SQL Server 中的 XQuery 实现。尽管 XQuery 在查询编译阶段使用自己的解析器并执行自己的代数化,但结果会与查询的 DML 部分一起组合和优化,然后组合成单个执行计划。
SQL Server 支持五种不同的方法。 value、exist、query和 nodes用于访问和转换数据。最后一个,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')
Run Code Online (Sandbox Code Playgroud)
会给你第一个订单的第一个客户的 ID
在您的特定情况下, value('.') 意味着从切碎的元素中给我所有值(我将在稍后讨论)请记住,在使用 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)
Run Code Online (Sandbox Code Playgroud)
对表中的 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)
Run Code Online (Sandbox Code Playgroud)
我在 value 和 node 上使用了示例,因为您仅提供了具有这两个函数的代码,如果您想阅读更多相关信息,请访问这里
希望这个简单的例子能让你了解如何查询 xml 类型