Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

SQL Server CTE dan contoh rekursi

Saya belum menguji kode Anda, hanya mencoba membantu Anda memahami cara kerjanya di komentar;

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

Contoh paling sederhana dari CTE rekursif Saya dapat memikirkan untuk menggambarkan operasinya adalah;

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

Q 1) bagaimana nilai N bertambah. jika nilai ditetapkan ke N setiap kali maka nilai N dapat bertambah tetapi hanya pertama kali nilai N diinisialisasi .

A1: Dalam hal ini, N bukan variabel. N adalah alias. Ini setara dengan SELECT 1 AS N . Ini adalah sintaks preferensi pribadi. Ada 2 metode utama kolom aliasing dalam CTE di T-SQL . Saya telah menyertakan analog dari CTE sederhana di Excel untuk mencoba dan mengilustrasikan dengan cara yang lebih familiar tentang apa yang sedang terjadi.

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

Q 2) sekarang di sini tentang CTE dan rekursi hubungan karyawansaat saya menambahkan dua manajer dan menambahkan beberapa karyawan lagi di bawah manajer kedua kemudian masalah dimulai. saya ingin menampilkan detail manajer pertama dan di baris berikutnya hanya detail karyawan tersebut yang akan datang mereka yang berada di bawah manajer tersebut

A2:

Apakah kode ini menjawab pertanyaan Anda?

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

Satu lagi sql dengan struktur pohon

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. Dapatkan tanggal dari nomor minggu di T-SQL

  2. Apakah mungkin untuk menggabungkan nilai kolom menjadi string menggunakan CTE?

  3. Memperbarui Data Salesforce dengan Kursor SQL Server

  4. Mendapatkan peringatan:Nilai nol dihilangkan dengan operasi SET agregat atau lainnya

  5. STRING_SPLIT() di SQL Server 2016 :Tindak Lanjut #2