我有一个表,其中包含一个 XML 列
XmlMsg
。此列可以包含 orderstatus
、vehiclestatus
、....
我只对
orderstatus
节点感兴趣,更确切地说,对以下两种情况感兴趣:
orderpart
是“待处理”。orderpart
是“待定”,最后一个是“已完成”。第一个示例如下(仅显示相关部分):
<orderstatus responsecode="0"
...
numberoforderparts="3">
...
<orderparts>
<orderpart orderpartnumber="1"/>
<orderpart orderpartnumber="2"/>
<orderpart orderpartnumber="3">
<eventtype>Pending</eventtype>
...
</orderpart>
</orderparts>
</orderstatus>
第二个示例如下(也仅显示相关部分):
<orderstatus responsecode="0"
...
numberoforderparts="3">
...
<orderparts>
<orderpart orderpartnumber="1"/>
<orderpart orderpartnumber="2">
<eventtype>Completed</eventtype>
...
</orderpart>
<orderpart orderpartnumber="3">
<eventtype>Pending</eventtype>
...
</orderpart>
</orderparts>
</orderstatus>
我可以通过此查询获取第一个列表:
SELECT *,
XmlMsg.value('(/orderstatus/@numberoforderparts)[1]', 'INT') AS NumberOfOrderParts,
-- Retrieve the last orderpart with eventtype="Pending"
XmlMsg.query('(/orderstatus/orderparts/orderpart[@orderpartnumber = (/orderstatus/@numberoforderparts)[1] and eventtype="Pending"])[1]') AS LastOrderPart,
-- Retrieve the second-to-last orderpart with eventtype="Completed"
XmlMsg.query('(/orderstatus/orderparts/orderpart[@orderpartnumber = (/orderstatus/@numberoforderparts)[1] - 1 and eventtype="Completed"])[1]') AS PreviousOrderPart
FROM
[dbo].[AWIMessageLogs]
WHERE
Source = 'RCV_RESP'
AND LogDateTime >= '2024-11-26'
AND LogDateTime <= '2024-11-26 15:00'
AND XmlMsg.exist('/orderstatus') = 1
-- Ensure that the last orderpart has eventtype="Pending"
AND XmlMsg.query('(/orderstatus/orderparts/orderpart[@orderpartnumber = (/orderstatus/@numberoforderparts)[1] and eventtype="Pending"])[1]') IS NOT NULL
但是,我不知道如何获得第二个列表。
有人有想法吗?
使用节点方法通常更容易获得这些东西,例如:
CREATE TABLE #xml (x xml, id int IDENTITY)
INSERT INTO #xml VALUES(N'<orderstatus responsecode="0"
numberoforderparts="3">
<orderparts>
<orderpart orderpartnumber="1"/>
<orderpart orderpartnumber="2"/>
<orderpart orderpartnumber="3">
<eventtype>Pending</eventtype>
</orderpart>
</orderparts>
</orderstatus>'), ('<orderstatus responsecode="0"
numberoforderparts="3">
<orderparts>
<orderpart orderpartnumber="1"/>
<orderpart orderpartnumber="2">
<eventtype>Complete</eventtype>
</orderpart>
<orderpart orderpartnumber="3">
<eventtype>Pending</eventtype>
</orderpart>
</orderparts>
</orderstatus>')
SELECT *
FROM (
SELECT *
, CASE
WHEN orderpart = max(orderpart) OVER(partition BY id) AND eventtype = 'Pending' -- Last pending
OR (
orderpart = max(orderpart) OVER(partition BY id) -1 AND eventtype = 'Complete' -- Complete and last is pending
AND LEAD(eventtype) OVER(PARTITION BY ID ORDER BY orderpart) = 'Pending'
)
THEN 1 ELSE 0 END AS flag
FROM (
SELECT op.value('@orderpartnumber', 'int') AS orderpart, et.value('text()[1]', 'nvarchar(100)') AS eventtype
, id
FROM #xml t
CROSS apply x.nodes(N'orderstatus/orderparts/orderpart') t1(op)
OUTER apply op.nodes(N'eventtype') t2(et)
) x
) x
WHERE flag = 1
然后您可以使用一些 LAG/LEAD 来查找相关值,或者将数据放入临时表中并从那里进行处理。
输出:
订购部分 | 事件类型 | id | 旗帜 |
---|---|---|---|
3 | 待定 | 1 | 1 |
2 | 完成 | 2 | 1 |
3 | 待定 | 2 | 1 |
最后一个订单部分是“待处理”。
orderstatus[orderparts/orderpart[last()]/eventtype='Pending']
最后一个订单部分是“待定”,最后一个订单部分是“完成”。
orderstatus[orderparts/orderpart[last()]/eventtype='Pending' and
orderparts/orderpart[last()-1]/eventtype='Complete']
您可以对这两个查询使用 XPath 1.0:
获取最后一个
orderstatus
为orderpart
的"Pending"
节点:
//orderstatus[
orderparts[
orderpart[last()][eventtype/text() = "Pending"]
]
]
获取最后一个
orderstatus
为orderpart
且倒数第二个为"Pending"
的"Complete"
节点:
//orderstatus[
orderparts[
orderpart[last()][eventtype/text() = "Pending"]
][
orderpart[last() - 1][eventtype/text() = "Complete"]
]
]