6

CTEを使用して難しい再帰であると私が信じていることを実行しようとしています。SQLServer2008です。これに頭を悩ませているようには見えません。

以下の例では、3の固定深度を想定できます...それよりも低くなることはありません。実生活では、深さは「より深い」ですが、それでも固定されています。例では、それをいくつか単純化しようとしました。

私の入力データは以下のようなものです。

ID     PARENT_ID       NAME          DEPTH
------------------------------------------
1      NULL            A             1
2      1               B             2
3      2               C             3
4      1               D             2

私のCTEの出力は次の表になります。

LEVEL1_ID    LEVEL2_ID    LEVEL3_ID    LEVEL1_NAME    LEVEL2_NAME    LEVEL3_NAME
--------------------------------------------------------------------------------
1            NULL         NULL         A              NULL           NULL
1            2            NULL         A              B              NULL
1            2            3            A              B              C
1            4            NULL         A              D              NULL

出力でID列を取得できれば、ルックアップテーブルの名前に確実にマップできます。

私は、SSISの使用を含め、これを達成する他の方法にもオープンです。

4

3 に答える 3

9

それほど難しいことではありません。

;WITH cte AS
(
    SELECT CAST('/' + Name AS VARCHAR(50)) as 'CteName', ID
    FROM dbo.YourTable
    WHERE parent_id IS NULL

    UNION ALL

    SELECT CAST(cte.CteName + '/' + Name AS VARCHAR(50)), t.ID
    FROM dbo.YourTable t
    INNER JOIN cte ON t.parent_id = cte.id
)
SELECT cteName FROM cte
ORDER BY ID

次の出力が得られます。

/A
/A/B
/A/B/C
/A/D

補足として:「深さ」はCTEによって簡単に計算でき、必ずしもテーブルに保存する必要はありません(Level追加した列を参照)。

;WITH cte AS
(
    SELECT 
       CAST('/' + Name AS VARCHAR(50)) as 'CteName', ID, 
       1 AS 'Level'
    FROM dbo.YourTable
    WHERE parent_id IS NULL

    UNION ALL

    SELECT 
       CAST(cte.CteName + '/' + Name AS VARCHAR(50)), t.ID,
       cte.Level + 1 AS 'Level'
    FROM dbo.YourTable t
    INNER JOIN cte ON t.parent_id = cte.id
)
SELECT cteName FROM cte
ORDER BY Level, ID
于 2010-07-01T15:27:35.787 に答える
0

cteでサブクエリを実行できることを覚えていません。

ここにSQLサーバーのコピーはありませんが、次のコードで試すことができます。

WITH cte(id, path, level)
AS
(
    SELECT id, '/' + name, level
    FROM yourtable
    WHERE level = 1

    UNION ALL

    SELECT y.id, c.name + '/' + y.name, y.level
    FROM yourtable y INNER JOIN
    cte c ON c.id = y.parent_id
    WHERE level = (SELECT max(level)+1 from cte)
)
SELECT path from cte
于 2010-07-01T15:33:37.387 に答える
-1
;WITH Vals AS (
        SELECT  CASE DEPTH WHEN 1 THEN ID ELSE NULL END 'LEVEL1_ID ',
                CASE DEPTH WHEN 2 THEN ID ELSE NULL END 'LEVEL2_ID ',
                CASE DEPTH WHEN 3 THEN ID ELSE NULL END 'LEVEL3_ID ',
                CASE DEPTH WHEN 1 THEN NAME ELSE NULL END 'LEVEL1_NAME',
                CASE DEPTH WHEN 2 THEN NAME ELSE NULL END 'LEVEL2_NAME',
                CASE DEPTH WHEN 3 THEN NAME ELSE NULL END 'LEVEL3_NAME',
                ID 'PRMID'                
        FROM    #Table1
        WHERE   parentId IS NULL
        UNION ALL
         SELECT  CASE DEPTH WHEN 1 THEN ID ELSE LEVEL1_ID END 'LEVEL1_ID ',
                CASE DEPTH WHEN 2 THEN ID ELSE LEVEL2_ID END 'LEVEL2_ID ',
                CASE DEPTH WHEN 3 THEN ID ELSE LEVEL3_ID END 'LEVEL3_ID ',
                CASE DEPTH WHEN 1 THEN NAME ELSE LEVEL1_NAME END 'LEVEL1_NAME',
                CASE DEPTH WHEN 2 THEN NAME ELSE LEVEL2_NAME END 'LEVEL2_NAME',
                CASE DEPTH WHEN 3 THEN NAME ELSE LEVEL3_NAME END 'LEVEL3_NAME',
                ID 'PRMID'                               
        FROM    #Table1 inner join Vals on #Table1.parentId=PRMID

)

SELECT  * from Vals
于 2013-10-24T13:44:51.143 に答える