我希望我得到這個正確:
你開始類型=「開始」和走的層次結構,其中出 - 數據是下一個節點的ID。該行具有未定義的深度,並且應該以具有type =「user」的節點結束。
你的第二個例子得到了2個任務,其中type =「user」,但其中只有一個被引用爲鏈上較高節點的out-data。
我的示例將使用額外的EXISTS
子句過濾第二個。
第一個CTE DerivedTable由您也可能使用的查詢組成。它將以表格形式提供完整的信息。
第二個CTE是遞歸的,從開始開始並遍歷鏈。列號等級是鏈的順序。
第三個CTE會添加一個反向排序,因爲您似乎只對最後一個項目感興趣。你可能會WHERE RevRank=1
DECLARE @process TABLE(ID INT IDENTITY, workflowXML XML);
INSERT INTO @process(workflowXML) VALUES
('<process>
<Event type="start" id="StartEvent_1">
<outgoing>SequenceFlow_0h5l5vu</outgoing>
</Event>
<Flow type="sequence"
id="SequenceFlow_0h5l5vu"
sourceRef="StartEvent_1"
targetRef="Task_1qc93ha"/>
<Flow type="sequence"
id="SequenceFlow_120gi3p"
sourceRef="Task_1qc93ha"
targetRef="Task_0x1pjee"/>
<Task type="service" id="Task_1qc93ha">
<incoming>SequenceFlow_0h5l5vu</incoming>
<outgoing>SequenceFlow_120gi3p</outgoing>
</Task>
<Task type="user" id="Task_0x1pjee">
<incoming>SequenceFlow_120gi3p</incoming>
</Task>
</process>')
,('<process id="Process_1" isExecutable="false">
<Event type="start" id="StartEvent_142xowk">
<outgoing>SequenceFlow_03yocm5</outgoing>
</Event>
<Flow type="sequence"
id="SequenceFlow_03yocm5"
sourceRef="StartEvent_142xowk"
targetRef="Task_12g1q69"/>
<Task type="user" id="Task_0x1pjee">
<incoming>SequenceFlow_120gi3p</incoming>
</Task>
<Task type="user" id="Task_12g1q69">
<incoming>SequenceFlow_03yocm5</incoming>
</Task>
</process>');
- 這得到這是查詢:
WITH DerivedTable AS
(
SELECT prTbl.ID AS tblID
,nd.value('local-name(.)','nvarchar(max)') AS [Name]
,nd.value('@type','nvarchar(max)') AS [Type]
,nd.value('@id','nvarchar(max)') AS Id
,COALESCE(nd.value('@sourceRef','nvarchar(max)')
,nd.value('(incoming)[1]','nvarchar(max)')) AS [In]
,COALESCE(nd.value('@targetRef','nvarchar(max)')
,nd.value('(outgoing)[1]','nvarchar(max)')) AS [Out]
FROM @process AS prTbl
CROSS APPLY prTbl.workflowXML.nodes('process') AS A(pr)
CROSS APPLY pr.nodes('*') AS B(nd)
)
,recCTE AS
(
SELECT tblID,[Name],[Type],Id,[In],[Out],1 AS [Rank]
FROM DerivedTable
WHERE [Type]='start'
UNION ALL
SELECT x.tblID,x.[Name],x.[Type],x.Id,x.[In],x.[Out],r.[Rank]+1
FROM recCTE AS r
INNER JOIN DerivedTable AS x ON x.[Id]=r.[Out]
AND EXISTS(SELECT 1
FROM DerivedTable AS y
WHERE y.tblID=x.tblID AND y.[Out]=x.[Id])
)
,ReverseRank AS
(
SELECT *
,ROW_NUMBER() OVER(PARTITION BY tblID ORDER BY [Rank] DESC) AS RevRank
FROM recCTE
)
SELECT *
FROM ReverseRank
ORDER BY tblID,[Rank]
結果(您的預計產量爲RevRank = 1):
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| tblID | Rank | RevRank | Name | Type | Id | In | Out |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| 1 | 1 | 5 | Event | start | StartEvent_1 | NULL | SequenceFlow_0h5l5vu |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| 1 | 2 | 4 | Flow | sequence | SequenceFlow_0h5l5vu | StartEvent_1 | Task_1qc93ha |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| 1 | 3 | 3 | Task | service | Task_1qc93ha | SequenceFlow_0h5l5vu | SequenceFlow_120gi3p |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| 1 | 4 | 2 | Flow | sequence | SequenceFlow_120gi3p | Task_1qc93ha | Task_0x1pjee |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| 1 | 5 | 1 | Task | user | Task_0x1pjee | SequenceFlow_120gi3p | NULL |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| 2 | 1 | 3 | Event | start | StartEvent_142xowk | NULL | SequenceFlow_03yocm5 |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| 2 | 2 | 2 | Flow | sequence | SequenceFlow_03yocm5 | StartEvent_142xowk | Task_12g1q69 |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
| 2 | 3 | 1 | Task | user | Task_12g1q69 | SequenceFlow_03yocm5 | NULL |
+-------+------+---------+-------+----------+----------------------+----------------------+----------------------+
UPDATE :您的評論
我用XM測試了我的查詢l在您的評論:
INSERT INTO @process(workflowXML) VALUES
('<process>
<Event type="start" id="e1">
<outgoing>s1</outgoing>
</Event>
<Flow type="sequence" id="s1" sourceRef="e1" targetRef="t1" />
<Flow type="sequence" id="s3" sourceRef="t1" targetRef="t2" />
<Task type="user" id="t3">
<incoming>s2</incoming>
</Task>
<Task type="user" id="t1">
<incoming>s1</incoming>
<outgoing>s3</outgoing>
</Task>
<Flow type="sequence" id="s2" sourceRef="t2" targetRef="t3" />
<Task type="service" id="t2">
<incoming>s3</incoming>
<outgoing>s2</outgoing>
</Task>
</process>');
這是結果
+-------+-------+----------+----+------+------+------+---------+
| tblID | Name | Type | Id | In | Out | Rank | RevRank |
+-------+-------+----------+----+------+------+------+---------+
| 1 | Event | start | e1 | NULL | s1 | 1 | 7 |
+-------+-------+----------+----+------+------+------+---------+
| 1 | Flow | sequence | s1 | e1 | t1 | 2 | 6 |
+-------+-------+----------+----+------+------+------+---------+
| 1 | Task | user | t1 | s1 | s3 | 3 | 5 |
+-------+-------+----------+----+------+------+------+---------+
| 1 | Flow | sequence | s3 | t1 | t2 | 4 | 4 |
+-------+-------+----------+----+------+------+------+---------+
| 1 | Task | service | t2 | s3 | s2 | 5 | 3 |
+-------+-------+----------+----+------+------+------+---------+
| 1 | Flow | sequence | s2 | t2 | t3 | 6 | 2 |
+-------+-------+----------+----+------+------+------+---------+
| 1 | Task | user | t3 | s2 | NULL | 7 | 1 |
+-------+-------+----------+----+------+------+------+---------+
如果我理解其中的邏輯正確我查詢工作只是罰款:
- 事件ID = E1點S1
- 流程s1指向t1
- 任務t1指向s3
- 流S3點到t2
- 任務T2點s2的
- 流S2點至t3
- 任務T3是結束
,我看到不同的唯一的事情,是一個事實,即任務t1已經是type =「user」。如果你想要的 - 在任何情況下 - 排名最高的用戶任務,你可能會帶走ReverseRank
-CTE和設置最終SELECT
像
SELECT t.*
FROM recCTE AS t
WHERE t.[Rank]<=ISNULL((SELECT MIN(x.[Rank]) FROM recCTE AS x WHERE x.tblID=t.tblID AND x.[Type]='user' AND x.[Name]='Task'),999)
ORDER BY t.tblID,t.[Rank]
現在任務T1將是最後的結果,其隨後所有的行列被過濾掉。
難道你不想將數據存儲在合適的表中而不是XML中嗎? –
@EvaldasBuinauskas不,我需要以XML格式存儲數據。 –
根據使用的方法,XML已經有方法來檢索重複節點(''//'')或返回水平列中的特定重複節點的方法('''') –