Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

SQL Server CTE i przykład rekurencji

Nie testowałem twojego kodu, po prostu próbowałem pomóc ci zrozumieć, jak działa w komentarzach;

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

Najprostszy przykład rekurencyjnego CTE Myślę, że aby zilustrować jego działanie;

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

P 1) jak zwiększa się wartość N. jeśli wartość jest przypisywana do N za każdym razem, wtedy wartość N może być zwiększana, ale tylko za pierwszym razem, gdy wartość N została zainicjowana .

A1: W tym przypadku N nie jest zmienną. N jest aliasem. Jest to odpowiednik SELECT 1 AS N . Jest to składnia osobistych preferencji. Istnieją 2 główne metody aliasowania kolumn w CTE w T-SQL . Dołączyłem analogię prostego CTE w Excel aby spróbować zilustrować w bardziej znany sposób, co się dzieje.

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

P 2) teraz tutaj o CTE i rekurencji relacji z pracownikamiw momencie dodania dwóch menedżerów i kilku kolejnych pracowników pod drugim menedżerem, a następnie rozpoczęcie problemu. Chcę wyświetlić szczegóły pierwszego menedżera, a w następnych wierszach pojawią się tylko te dane pracownika ci, którzy są podwładni tego menedżera

A2:

Czy ten kod odpowiada na Twoje pytanie?

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

Kolejny sql ze strukturą drzewa

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jaka jest najlepsza praktyka wstawiania rekordu, jeśli jeszcze nie istnieje?

  2. Zwróć typ wyzwalacza DML w tabeli w SQL Server

  3. SQL Server v.Next :Wydajność STRING_AGG()

  4. Jak dodać domyślne ograniczenie do istniejących kolumn w tabeli SQL Server — samouczek SQL Server/TSQL — część 91

  5. Połącz się z bazą danych MSSQL za pomocą Flask-SQLAlchemy