MW211 EXIT

devlog
MSSQL/Key-Valueチェーン
2018年08月03日
Key-Value形式のテーブルで、Valueに他のKeyがある場合
それを繋げて最終的なValueを取得するSQL文。
なお、循環(無限ループ)の場合は、最初の階層の結果を返却する。
┌──────────────────────────────────────┐
│WITH [起点] (                                                               │
│        [キー],                                                             │
│        [バリュー]                                                          │
│    ) AS (                                                                  │
│        SELECT [キー],                                                      │
│               [バリュー]                                                   │
│            FROM 表 [表]                                                    │
│            WHERE [キー] = 値                                               │
│    ),                                                                      │
│    [再帰] (                                                                │
│        [キー],                                                             │
│        [階層],                                                             │
│        [直前キー],                                                         │
│        [バリュー],                                                         │
│        [循環]                                                              │
│    ) AS (                                                                  │
│        SELECT [キー],                                                      │
│               1                 AS [階層],                                 │
│               [キー]            AS [直前キー],                             │
│               [バリュー],                                                  │
│               0                 AS [循環]                                  │
│            FROM [起点]                                                     │
│        UNION ALL                                                           │
│        SELECT [再帰].[キー],                                               │
│               [再帰].[階層] + 1 AS [階層],                                 │
│               [表].[キー]       AS [直前キー],                             │
│               [表].[バリュー],                                             │
│               CASE                                                         │
│                 WHEN [再帰].[キー] = [表].[バリュー]                       │
│                   OR [再帰].[階層] > 99              THEN 1                │
│                 ELSE                                      0                │
│               END AS [循環]                                                │
│            FROM [再帰]                                                     │
│                INNER JOIN 表 AS [表]                                       │
│                  ON [表].[キー] = [再帰].[バリュー]                        │
│            WHERE [再帰].[循環] = 0                                         │
│    )                                                                       │
│SELECT [キー],                                                              │
│       [階層],                                                              │
│       [直前キー],                                                          │
│       [バリュー]                                                           │
│    FROM [再帰]                                                             │
│    WHERE [循環] = 0                                                        │
│      AND NOT EXISTS (                                                      │
│              SELECT *                                                      │
│                  FROM [再帰] AS [他]                                       │
│                  WHERE [他].[階層] > [再帰].[階層]                         │
│          )                                                                 │
│UNION ALL                                                                   │
│SELECT [キー],                                                              │
│       NULL       AS [階層],                                                │
│       NULL       AS [直前キー],                                            │
│       [バリュー]                                                           │
│    FROM [起点]                                                             │
│    WHERE EXISTS (                                                          │
│              SELECT *                                                      │
│                  FROM [再帰]                                               │
│                  WHERE [循環] = 1                                          │
│          )                                                                 │
└──────────────────────────────────────┘
分類:MSSQL