使用xquery从xml中提取数据的最佳方法
考虑以下 xml:
<Persons num="3">
<Person age="5" />
<Person age="19" />
</Persons>
需要将此 xml 提取到关系表中:
Persons table (Age1 int, Age2 int, Age3 int , Age4 int)
解析必须满足以下约束:
- 所有年龄 >=18 的人必须分配到列号最小的列,并且该值必须为 18
- 如果未给出该人的年龄,则等于 18
- 所有年龄 <18 岁的人都必须遵循
- 如果少于 4 人,则未提供的人必须年龄=-1
在给定的示例中,有 3人,提供其中 2 人的年龄:分别为 5 岁和 19 岁。 Persons 表的内容必须如下所示:
18 18 5 -1
是否有使用 xpath 执行此操作的最佳方法?
到目前为止,我可以解析 xml 并分配年龄,但不清楚的是如何进行排序:
declare @XmlData xml =
'<Persons num="3">
<Person age="5" />
<Person age="19" />
</Persons>'
declare @Persons table (Age1 int, Age2 int, Age3 int , Age4 int)
insert into @Persons (Age1, Age2, Age3, Age4)
select ISNULL(Age1, case when Num>= 1 then 18 else -1 end) Age1
, ISNULL(Age2, case when Num>= 2 then 18 else -1 end) Age2
, ISNULL(Age3, case when Num>= 3 then 18 else -1 end) Age3
, ISNULL(Age4, case when Num>= 4 then 18 else -1 end) Age4
from (
select Persons.Person.value('@num','smallint') as Num
,Persons.Person.value('Person[@age<18][1]/@age','smallint') as Age1
,Persons.Person.value('Person[@age<18][2]/@age','smallint') as Age2
,Persons.Person.value('Person[@age<18][3]/@age','smallint') as Age3
,Persons.Person.value('Person[@age<18][4]/@age','smallint') as Age4
from @XmlData.nodes('/Persons') Persons(Person)
) Persons
select *
from @Persons
结果是
5 18 18 -1
Consider the following xml:
<Persons num="3">
<Person age="5" />
<Person age="19" />
</Persons>
There is a need to extract this xml into a relational table:
Persons table (Age1 int, Age2 int, Age3 int , Age4 int)
Parsing has to satisfy the following constraints:
- all persons with age >=18 must be assigned to columns with smallest column number and the value has to be 18
- if the age of the person is not given it is equal to 18
- all persons with age <18 must follow
- if there are less than 4 persons, those which are not provided must have age=-1
In a given example, there are 3 persons, ages of 2 of them are provided: 5 and 19 respectively. The content of the table Persons has to be the following:
18 18 5 -1
Is there the best way to do so with xpath?
Till now I can parse the xml and assign ages but what is not clear is to how make ordering:
declare @XmlData xml =
'<Persons num="3">
<Person age="5" />
<Person age="19" />
</Persons>'
declare @Persons table (Age1 int, Age2 int, Age3 int , Age4 int)
insert into @Persons (Age1, Age2, Age3, Age4)
select ISNULL(Age1, case when Num>= 1 then 18 else -1 end) Age1
, ISNULL(Age2, case when Num>= 2 then 18 else -1 end) Age2
, ISNULL(Age3, case when Num>= 3 then 18 else -1 end) Age3
, ISNULL(Age4, case when Num>= 4 then 18 else -1 end) Age4
from (
select Persons.Person.value('@num','smallint') as Num
,Persons.Person.value('Person[@age<18][1]/@age','smallint') as Age1
,Persons.Person.value('Person[@age<18][2]/@age','smallint') as Age2
,Persons.Person.value('Person[@age<18][3]/@age','smallint') as Age3
,Persons.Person.value('Person[@age<18][4]/@age','smallint') as Age4
from @XmlData.nodes('/Persons') Persons(Person)
) Persons
select *
from @Persons
Result is
5 18 18 -1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
另一种解决方案需要更多的 sql 代码,但预计执行计划的成本仅为 80 左右。
问题陈述有一个约束:Persons/@num必须等于许多Person标签
限制是:
这是sql代码:
Another solution requires a bit more sql code but costs only ~80 in estimated execution plan.
There is one constraint wrt the problem statement: Persons/@num has to be equal to a number of Person tags
Limitations are:
Here is sql code:
我发现了一个有点肮脏的解决方案:
解决方案的想法是首先提取那些>=18的联系人,然后提取那些0<=18的联系人。年龄< 18 最后将未提供的设置为 -1
UPD:尽管解决方案提供了正确的结果,但其成本很高:估计执行计划中约为 1000
I have found a bit dirty solution:
The idea of a solution is to first extract those contacts that are >=18, then extract those that are 0 < age < 18 and finally set those that are not provided to -1
UPD: despite the fact that solution provided correct results, its cost is high: ~1000 in estimated execution plan