sql >> データベース >  >> RDS >> Sqlserver

SQLServerCTEと再帰の例

    私はあなたのコードをテストしていません。コメントでどのように動作するかを理解するのを助けることを試みました;

    WITH
      cteReports (EmpID, FirstName, LastName, MgrID, EmpLevel)
      AS
      (
    -->>>>>>>>>>Block 1>>>>>>>>>>>>>>>>>
    -- In a rCTE, this block is called an [Anchor]
    -- The query finds all root nodes as described by WHERE ManagerID IS NULL
        SELECT EmployeeID, FirstName, LastName, ManagerID, 1
        FROM Employees
        WHERE ManagerID IS NULL
    -->>>>>>>>>>Block 1>>>>>>>>>>>>>>>>>
        UNION ALL
    -->>>>>>>>>>Block 2>>>>>>>>>>>>>>>>>    
    -- This is the recursive expression of the rCTE
    -- On the first "execution" it will query data in [Employees],
    -- relative to the [Anchor] above.
    -- This will produce a resultset, we will call it R{1} and it is JOINed to [Employees]
    -- as defined by the hierarchy
    -- Subsequent "executions" of this block will reference R{n-1}
        SELECT e.EmployeeID, e.FirstName, e.LastName, e.ManagerID,
          r.EmpLevel + 1
        FROM Employees e
          INNER JOIN cteReports r
            ON e.ManagerID = r.EmpID
    -->>>>>>>>>>Block 2>>>>>>>>>>>>>>>>>
      )
    SELECT
      FirstName + ' ' + LastName AS FullName,
      EmpLevel,
      (SELECT FirstName + ' ' + LastName FROM Employees
        WHERE EmployeeID = cteReports.MgrID) AS Manager
    FROM cteReports
    ORDER BY EmpLevel, MgrID
    

    再帰的なCTEの最も単純な例 その動作を説明するために考えることができます;

    ;WITH Numbers AS
    (
        SELECT n = 1
        UNION ALL
        SELECT n + 1
        FROM Numbers
        WHERE n+1 <= 10
    )
    SELECT n
    FROM Numbers
    

    Q 1)Nの値がどのように増加しているか。値が毎回Nに割り当てられる場合、N値はインクリメントできますが、最初にN値が初期化された場合のみ

    A1: この場合、N 変数ではありません。 N エイリアスです。これは、SELECT 1 AS Nと同等です。 。これは個人的な好みの構文です。 CTEの列をエイリアシングする主な方法は2つあります。 T-SQLで 。単純なCTEのアナログを含めました Excelで 何が起こっているのかをより身近な方法で説明しようとします。

    --  Outside
    ;WITH CTE (MyColName) AS
    (
        SELECT 1
    )
    -- Inside
    ;WITH CTE AS
    (
        SELECT 1 AS MyColName
        -- Or
        SELECT MyColName = 1  
        -- Etc...
    )
    

    Q 2)CTEと従業員関係の再帰についてここで、2人のマネージャーを追加し、2番目のマネージャーの下にさらに数人の従業員を追加してから問題を開始します。最初のマネージャーの詳細を表示したいのですが、次の行にはそれらの従業員の詳細のみが表示されますそのマネージャーの部下である人

    A2:

    このコードはあなたの質問に答えますか?

    --------------------------------------------
    -- Synthesise table with non-recursive CTE
    --------------------------------------------
    ;WITH Employee (ID, Name, MgrID) AS 
    (
        SELECT 1,      'Keith',      NULL   UNION ALL
        SELECT 2,      'Josh',       1      UNION ALL
        SELECT 3,      'Robin',      1      UNION ALL
        SELECT 4,      'Raja',       2      UNION ALL
        SELECT 5,      'Tridip',     NULL   UNION ALL
        SELECT 6,      'Arijit',     5      UNION ALL
        SELECT 7,      'Amit',       5      UNION ALL
        SELECT 8,      'Dev',        6   
    )
    --------------------------------------------
    -- Recursive CTE - Chained to the above CTE
    --------------------------------------------
    ,Hierarchy AS
    (
        --  Anchor
        SELECT   ID
                ,Name
                ,MgrID
                ,nLevel = 1
                ,Family = ROW_NUMBER() OVER (ORDER BY Name)
        FROM Employee
        WHERE MgrID IS NULL
    
        UNION ALL
        --  Recursive query
        SELECT   E.ID
                ,E.Name
                ,E.MgrID
                ,H.nLevel+1
                ,Family
        FROM Employee   E
        JOIN Hierarchy  H ON E.MgrID = H.ID
    )
    SELECT *
    FROM Hierarchy
    ORDER BY Family, nLevel
    

    ツリー構造を持つもう1つのSQL

    SELECT ID,space(nLevel+
                        (CASE WHEN nLevel > 1 THEN nLevel ELSE 0 END)
                    )+Name
    FROM Hierarchy
    ORDER BY Family, nLevel
    


    1. 条件付き集計のパフォーマンス

    2. Amazonec2のリモートpostgresqlサーバーに接続します

    3. ウィンドウ関数または共通テーブル式:範囲内の前の行をカウントします

    4. SQLite SUM