web-dev-qa-db-ja.com

CTEを使用した従業員の「名前」の階層:正しいバージョンを作成できません

Sql(CTE)クエリの正しい構造を作成しようとしていますが、できません。これは私が欲しいバージョンです correct version

そしてこれは私の現在のバージョンです: what i have now。ご覧のとおり、重複があり、それらを取り除く方法がわかりません。さらに、構造が間違っています。私はすでにここのような解決策を探そうとしましたが、解決策を思い付くことができませんでした。 CTEクエリは正しい構造を出力しませんか?

私の従業員テーブルは次のようになります http://sqlfiddle.com/#!6/428d2/2

正しい名前の列を作成するために使用するSQLクエリは次のとおりです。 http://sqlfiddle.com/#!6/bf4c1/4

私はMsSQL2012を使用しているので、最新の機能などを自由に使用してください。

1
johnmalc

CTEでルートノードを指定すると、問題なく機能します。

WITH Empl_Tab( Id ,
                 ParentId ,
                 LEVEL,
             [Order]
) AS ( SELECT Employee.[EMPl Id] ,  Employee.[reports to the Boss] ,
                0 AS LEVEL ,
              CONVERT([varchar](MAX), Employee.[EMPl Id]) AS [Order]
           FROM Employee
where [reports to the Boss] = 1
        UNION ALL

        SELECT Employee.[EMPl Id] ,
                Employee.[reports to the Boss] ,
                Empl_Tab.LEVEL+1 AS LEVEL ,
             Empl_Tab.[Order] + CONVERT([varchar](30), Employee.[EMPl Id]) AS [Order]
           FROM
                Employee INNER JOIN Empl_Tab
                ON Empl_Tab.Id = Employee.[reports to the Boss] 
     )

SELECT REPLICATE( '.' ,Empl_Tab.Id*1 )+Employee.Name AS Name
  FROM
       Employee INNER JOIN Empl_Tab
       ON Empl_Tab.Id = Employee.[EMPl Id]
  ORDER BY Empl_Tab.[Order]

SQL Fiddle here

2
Philᵀᴹ

SQLFiddle でコードを見ると、キーポイントだけが欠落しているため、正しい方向に進んでいます。

構文(BOLから) 再帰的CTEの==は:

WITH cte_name ( column_name [,...n] )
AS
(
CTE_query_definition –- Anchor member is defined.
UNION ALL
CTE_query_definition –- Recursive member is defined referencing cte_name.
)
-- Statement using the CTE
SELECT *
FROM cte_name

階層の最上位レベルである基本結果セットの作成が欠落しています。これは[reports to the Boss] = 1で識別されます。したがって、誰にも報告しないCEOがいる可能性がある場合、彼はそれをNULLに設定します。

SELECT Employee.[EMPl Id] ,  Employee.[reports to the Boss] ,
                0 AS LEVEL ,
              CONVERT([varchar](MAX), Employee.[EMPl Id]) AS [Order]
           FROM Employee
where [reports to the Boss] = 1

フィドルの残りのクエリは問題ないようです。

表示した結果を取得するには、以下が機能します。

;WITH Empl_Tab( Id ,
                 ParentId ,
                 LEVEL,
             [Order]
) AS ( SELECT Employee.[EMPl Id] ,  Employee.[reports to the Boss] ,
                0 AS LEVEL ,
              CONVERT([varchar](MAX), Employee.[EMPl Id]) AS [Order]
           FROM Employee
where [reports to the Boss] = 1
        UNION ALL

        SELECT Employee.[EMPl Id] ,
                Employee.[reports to the Boss] ,
                Empl_Tab.LEVEL+1 AS LEVEL ,
             Empl_Tab.[Order] + CONVERT([varchar](30), Employee.[EMPl Id]) AS [Order]
           FROM
                Employee INNER JOIN Empl_Tab
                ON Empl_Tab.Id = Employee.[reports to the Boss] 
     )

SELECT REPLICATE( ' ' ,Empl_Tab.Id*1 )+Employee.Name AS NAME,
        Id as EMPID,
        ParentId as SUPERVISORFK,
        POSITION
  FROM
       Employee INNER JOIN Empl_Tab
       ON Empl_Tab.Id = Employee.[EMPl Id]
  ORDER BY Empl_Tab.[Order]

enter image description here

それが理解に役立つことを願っています。

また、@ Philがフィドルに持っているクエリを見てください。

2
Kin Shah