我有一个表,其中包含 XML 列 XmlMsg。此 XmlMsg 可以包含“orderstatus”、“vehiclestatus”、....
我只对“orderstatus”感兴趣,更确切地说,对以下两种情况感兴趣:
第一个示例如下(仅显示相关部分):
<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 *,
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="Complete"
XmlMsg.query('(/orderstatus/orderparts/orderpart[@orderpartnumber = (/orderstatus/@numberoforderparts)[1] - 1 and eventtype="Complete"])[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 |