我希望我得到这个正确:
你开始类型=“开始”和走的层次结构,其中出 - 数据是下一个节点的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已经有方法来检索重复节点(''//'')或返回水平列中的特定重复节点的方法('''') –