2017-03-23 5 views
1

Ich möchte alle Mitarbeiter unter einem bestimmten Manager anzeigen. Alle Mitarbeiter haben die Benutzer-ID ihres unmittelbaren Vorgesetzten in ihrem Benutzerdatensatz, aber nicht den Vorgesetzten über ihnen. Im Grunde versuche ich, wenn ich eine ID des Regisseurs lege, die 2 Stufen über mir liegt, möchte ich meine ID zusammen mit allen anderen unter diesem Regisseur sehen. Ist das möglich SQL Server 2012?Durchlaufen einer Verwaltungsstruktur in SQL Server 2012

Antwort

0

Sie suchen nach einer hierarchischen oder rekursiven Abfrage.

Um die Hierarchie unter einem bestimmten Manager zu bekommen, statt den Baum an der Spitze

Verwurzelung
SELECT EmployeeID, FirstName, LastName, ManagerID, 1 
    FROM Employees 
    WHERE ManagerID IS NULL 

Sie den Baum an der gewünschten Manager

SELECT EmployeeID, FirstName, LastName, ManagerID, 1 
    FROM Employees 
    WHERE ManagerID = @QueryManagerID 
0

Hier ist eine eher allgemeine rekursive Wurzel würde CTE für eine eher allgemeine quesion

Beispiel

Declare @YourTable table (UserID varchar(25),ManagerID varchar(25),Name varchar(50)) 
Insert into @YourTable values 
('usr1' ,NULL ,'A') 
,('usr2' ,'usr1' ,'B') 
,('usr3' ,'usr2' ,'F') 
,('usr4' ,'usr3' ,'C') 
,('usr5' ,'usr3' ,'D') 
,('usr8' ,'usr1' ,'M') 
,('usr9' ,'usr8' ,'N') 
,('usr10','usr8' ,'O') 
,('usr11','usr10','P') 

Declare @Top varchar(25) = null  --<< Sets top of Hier Try usr3 
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability 

;with cteP as (
     Select Seq = cast(10000+Row_Number() over (Order by Name) as varchar(500)) 
      ,UserID 
      ,ManagerID 
      ,Lvl=1 
      ,Name 
     From @YourTable 
     Where IsNull(@Top,-1) = case when @Top is null then isnull(ManagerID ,-1) else UserID end 
     Union All 
     Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.Name)) as varchar(500)) 
      ,r.UserID 
      ,r.ManagerID 
      ,p.Lvl+1 
      ,r.Name 
     From @YourTable r 
     Join cteP p on r.ManagerID = p.UserID) 
    ,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP) 
    ,cteR2 as (Select A.UserID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.UserID) 
Select A.R1 
     ,B.R2 
     ,A.UserID 
     ,A.ManagerID 
     ,A.Lvl 
     ,Name = Replicate(@Nest,A.Lvl-1) + A.Name 
From cteR1 A 
Join cteR2 B on A.UserID=B.UserID 
Order By Seq 

Returns Voll Hierarchy (wenn @Top = null)

enter image description here

Returns Hierarchie Portion (wenn @Top = 'someUserID')

enter image description here

Ein paar Kommentare

Sie können die Bereichsschlüssel (R1/R2) bemerken. Diese sind optional und können entfernt werden. Sie unterstützen jedoch die Navigation, Auswahl und/oder Aggregation, ohne dass rekursive Abfragen erforderlich sind.

Die meisten Verwaltungshierarchien sind langsam, daher würde ich empfehlen, die Ergebnisse in einer tatsächlichen Tabelle zu speichern und bei Bedarf neu zu erstellen. Dies wäre leistungsfähiger, besonders wenn Sie eine große Organisation haben. Dies führt mich zu einem letzten Punkt. GROSSE rekursive CTEs tendieren nicht dazu, gut zu funktionieren. Es gibt andere Techniken, die eingesetzt werden können:

+0

Ich würde einen Pfad zu Ihrem generischen Hierarchie-Traversal hinzufügen, er kann auch die Lesbarkeit unterstützen, z. http://rexttester.com/KIZQRE86151 – SqlZim

+0

@SqlZim Immer eine gute Option, aber ich habe festgestellt, dass die Bereichsschlüssel eine bessere Leistung bieten, insbesondere beim Navigieren in großen Hierarchien (200K +) und beim Aggregieren großer Datenmengen (4,6B Zeilen). Im Laufe der Zeit habe ich eine Sammlung von Hilfsfunktionen zum Verwalten und Navigieren erstellt. Vor Jahren dachte ich, ich wäre der klügste Typ auf zwei Beinen, wenn ich die Range Keys "erfunden" hätte. Ich diskutierte sie mit einem IBM Berater, und er lehnte sich leise vor und sagte: "Wir nennen sie die Speed ​​Keys" –

+0

@SqlZim ... Nichts Neues unter der Sonne ... –