SQL Server 2008 R2 データベースに、異なる状態間の遷移を定義するテーブルがあります。
関連する表の列の例:
TransitionID | SourceStateID | DestinationStateID | WorkflowID
--------------------------------------------------------------
1 | 17 | 18 | 3
2 | 17 | 21 | 3
3 | 17 | 24 | 3
4 | 17 | 172 | 3
5 | 18 | 17 | 3
6 | 18 | 24 | 3
7 | 18 | 31 | 3
8 | 21 | 17 | 3
9 | 21 | 20 | 3
10 | 21 | 141 | 3
11 | 21 | 184 | 3
...など
私の目標は、開始StateID、終了StateID、および WorkflowID を定義し、できればそのワークフロー内で開始 StateID から終了 StateID への論理パスを見つけられるようにすることです。
たとえば、上の表の場合、開始 StateID を 17、終了 StateID を 184、WorkflowID を 3 にすると、「パス」は 17>21>184 (より理想的には、TransitionID 2 >トランジションID 11)
いいもの:
- 定義された開始および終了 StateIDには、定義された WorkflowID 内の可能なパスが常にあります。
悪い人:
ほぼすべての送信元/送信先の StateID に確かに循環参照があります (つまり、SourceStateID 1 から DestinationStateID 2 への遷移と、SourceStateID 2 から DestinationStateID 1 への遷移がある可能性があります)。
事実上、定義された開始 StateID と終了 StateID からの複数の可能なパスが確かに存在します。
私が求めているのはある種のCTEであることはわかっていますが、CTEは一般的に把握するのが難しいことを認めており、循環参照が保証された問題である場合は2倍になります。
完璧な解決策は、StateID の開始から StateID の終了までの最短パスを選択することですが、この時点で正直に言うと、2 つの状態の間の有効なパスを確実に提供する何かが機能する場合は、そうします。ハッピー。
そこにいるSQLの専門家は、あなたが私に指摘できる方向性を持っていますか? 正直なところ、17>18>17>18>17>18...
不快な更新 私は感情的なレベルで私を傷つけるこのクエリを思いつきました(この投稿の助けを借りて:https://stackoverflow.com/a/11042012/3253311)が、機能しているようです。
DECLARE @sourceStatusId INT = 17
DECLARE @destinationStatusId INT = 24
DECLARE @workflowId INT = 3
DECLARE @sourceStatusIdString NVARCHAR(MAX) = CAST(@sourceStatusId AS NVARCHAR(MAX))
DECLARE @destinationStatusIdString NVARCHAR(MAX) = CAST(@destinationStatusId AS NVARCHAR(MAX))
DECLARE @workflowIdString NVARCHAR(MAX) = CAST(@workflowId AS NVARCHAR(MAX))
;WITH CTE ([Source], [Destination], [Sentinel]) AS
(
SELECT
CAST(t.[Source] AS NVARCHAR(MAX)) AS [Source],
CAST(t.[Destination] AS NVARCHAR(MAX)) AS [Destination],
[Sentinel] = CAST([Source] AS NVARCHAR(MAX))
FROM
Transitions t
WHERE
CAST([Source] AS NVARCHAR(MAX)) = @sourceStatusIdString AND
CAST([WorkflowID] AS NVARCHAR(MAX)) = @workflowIdString
UNION ALL
SELECT
CAST(CTE.[Destination] AS NVARCHAR(MAX)),
CAST(t.[Destination] AS NVARCHAR(MAX)),
CAST([Sentinel] AS NVARCHAR(MAX)) + CAST('|' AS NVARCHAR(MAX)) + CAST(CTE.[Destination] AS NVARCHAR(MAX))
FROM
CTE
JOIN Transitions t
ON CAST(t.[Source] AS NVARCHAR(MAX)) = CAST(CTE.[Destination] AS NVARCHAR(MAX))
WHERE
CHARINDEX(CTE.[Destination], Sentinel)=0
)
SELECT TOP 1
[Sentinel]
FROM
CTE
WHERE
LEFT([Sentinel], LEN(@sourceStatusIdString)) = @sourceStatusIdString AND
RIGHT([Sentinel], LEN(@destinationStatusIdString)) = @destinationStatusIdString
ORDER BY
LEN([Sentinel])