sql >> Databáze >  >> RDS >> Sqlserver

SQL Server CTE a příklad rekurze

Váš kód jsem netestoval, jen jsem se vám pokusil pomoci pochopit, jak funguje v komentáři;

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

Nejjednodušší příklad rekurzivního CTE Dovedu si představit, že jeho fungování je;

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

O 1) jak se zvyšuje hodnota N. pokud je hodnota přiřazena k N pokaždé, pak lze hodnotu N zvýšit, ale pouze při první inicializaci hodnoty N .

A1: V tomto případě N není proměnná. N je alias. Je ekvivalentem SELECT 1 AS N . Je to syntaxe osobních preferencí. Existují 2 hlavní metody aliasování sloupců v CTE v T-SQL . Zahrnul jsem analog jednoduchého CTE v Excel pokusit se ilustrovat známějším způsobem, co se děje.

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

O 2) nyní zde o CTE a rekurzi zaměstnaneckého vztahu, jakmile přidám dva manažery a přidám několik dalších zaměstnanců pod druhého manažera, pak začne problém. Chci zobrazit detail prvního manažera a v dalších řádcích se objeví pouze tyto podrobnosti o zaměstnancích ti, kteří jsou tomu manažerovi podřízení

A2:

Odpovídá tento kód na vaši otázku?

--------------------------------------------
-- 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

Další sql se stromovou strukturou

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


  1. Jak vložit řádky do tabulky SQL Server pomocí GUI pro úpravy řádků tabulky - SQL Server / Výukový program TSQL, část 101

  2. Rozdíl mezi #temptable a ##TempTable?

  3. Příklad Spring Boot CRUD s MySQL

  4. Funkce NVL() v Oracle