gpt4 book ai didi

xpath - 如果节点存在于某个位置,xquery 返回 bool 值

转载 作者:行者123 更新时间:2023-12-03 16:20:15 24 4
gpt4 key购买 nike

我在 SQL 2008 数据库中有类似于以下内容的 XML,存储在 XML 字段中。如果节点存在于 XML 的特定部分中,我想返回真或假指示。

<root>
<node attribute1='value1' attribute2='value2'>
<sub1 name='ID' value="1" />
<sub2 name='project' value="abc" />
<sub3 name='Lead' value="John" />
</node>
<entry attribute1='value1' attribute2='value2'>
<message>start</message>
</entry>
<entry attribute1='value1' attribute2='value2'>
<attribute name='project' value='done'>
</entry>
<node attribute1='value1'>
<sub1 name='ID' value="2" />
<sub2 name='project' value="abc" />
<sub3 name='Lead' value="John" />
</node>
<entry attribute1='value1' attribute2='value2'>
<message>start</message>
</entry>
<node attribute1='value1'>
<sub1 name='ID' value="3" />
<sub2 name='project' value="abc" />
<sub3 name='Lead' value="John" />
</node>
<entry attribute1='value1' attribute2='value2'>
<message>start</message>
</entry>
<node attribute1='value1'>
<sub1 name='ID' value="4" />
<sub2 name='project' value="abc" />
<sub3 name='Lead' value="John" />
</node>
<entry attribute1='value1' attribute2='value2'>
<message>start</message>
</entry>
<entry attribute1='value1' attribute2='value2'>
<attribute name='project' value='done'>
</entry>
</root>

如您所见, <attribute>节点可能会或可能不会出现在具有“ID”的节点之后。在此示例中,您可以在第一和第四“部分”中看到它,因为没有更好的术语。

具有以下表结构:
ID (PK)
EventID (FK)
RawXML (XML)
Created (datetime)

以下是我目前所拥有的 SQL/xQuery 的摘录:
WITH XMLNAMESPACES(
'http://www.w3.org/2001/XMLSchema-instance' as xsi,
),
t1 as(
SELECT distinct
x.EventId
, c.value ('(//node/sub[@name=''ID'']/@value)[1]', 'nvarchar(max)') as ID
, c.value ('(//node/sub[@name=''ID''][1][descendant::attribute/@name=''project''])[1]', 'nvarchar(max)' ) as Exists
FROM
Table1 x
CROSS APPLY
RawXML.nodes('./.') as t(c)
)
select distinct
t1.ID
, t1.Exists
from t1

我将运行脚本 4 次或更多次(在每次运行之前递增所有单例值)

对于给定的 XML,我需要在运行 4 次查询后得到以下结果:
(不知道 ID 的值,所以我不能在查询中使用它们)
    ID    Exists
---- -------
1 true
2 false
3 false
4 true

给出 SQL 后,我没有收到任何错误,但它需要很长时间(超过 45 分钟),我什至还没有让它完成。解析 XML 真的不应该花这么长时间。

更新:我限制了我的查询以确保它只解析一行(一个 XML 文件)并在 57 秒内完成。但是,当我应该为 ID 1 获得“1”时,我得到了 ID 1 和 ID 2 的“0”结果。

而且我相信你们中的大多数人都知道 SQL Server 不支持以下 sibling 等,所以很遗憾,这不是一个选项。

仅供引用,我已经成功地使用它来找到“项目”的两个实例,但它忽略了它们在 xml 中出现的位置。:
c.value ('(//node[descendant::attribute/@name=''Project''])[1]', 'nvarchar(max)' ) as TrueFalse

所以基本上,我需要知道名称='Project'的节点是否存在于名称='ID'的节点之后,但在名称='ID'的节点的下一个实例之前

最佳答案

您的 XML 中有一些错误,根据您使用的查询判断,我还更改了子节点。

您可以使用 row_number() 枚举您的 ID 和项目节点。然后使用常规 SQL 而不是 XQuery 检查“下一行”是项目节点还是 ID 行。

-- Temp table to hold the extracted values from the XML
create table #C
(
rn int primary key,
ID int
);

-- Get the enumerated rows with ID.
-- project nodes will have NULL in ID
insert into #C
select row_number() over(order by T.N) as rn,
T.N.value('sub[@name = "ID"][1]/@value', 'int') as ID
from table1
cross apply RawXML.nodes('/root/*[sub/@name = "ID" or attribute/@name = "project"]') as T(N)

-- Get the ID's and check if the next row is a project node
select C1.ID,
case when exists (
select *
from #C as C2
where C1.rn + 1 = C2.rn and
C2.ID is null
)
then 1
else 0
end as [Exists]
from #C as C1
where C1.ID is not null;

drop table #C;

SQL Fiddle

您可以在没有临时表的情况下使用 CTE 来代替,但我怀疑临时表版本会更快。

with C as
(
select row_number() over(order by T.N) as rn,
T.N.value('sub[@name = "ID"][1]/@value', 'int') as ID
from table1
cross apply RawXML.nodes('/root/*[sub/@name = "ID" or attribute/@name = "project"]') as T(N)
)
select C1.ID,
case when exists (
select *
from C as C2
where C1.rn + 1 = C2.rn and
C2.ID is null
)
then 1
else 0
end as [Exists]
from C as C1
where C1.ID is not null;

SQL Fiddle

关于xpath - 如果节点存在于某个位置,xquery 返回 bool 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13036830/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com