22 messaggi dal 27 marzo 2003
Buongiorno,
in sql server 2008 ho un db fatto così:
id, username, idResponsabile.
è l'elenco dei dipendenti di un'azienda, ognuno ha un id e uno username e il proprio responsabile, gerarchicamente fino al direttore dove l'idresponsabile è NULL.
Devo ottenere un elenco di tutti i subordinati di un dirigente, che sotto ha poniamo tre livelli,
esempio:
direttore generale= Disney
dirigente: Topolino, che ha come subordinato Pluto
dirigente: Pippo che è da solo
dirigente: Zio Paperone, ha come subordinati: Paperino, che a sua volta sotto ha Qui-Quo-Qua,
Nonna Papera che a sua volta sotto ha Ciccio.
Se seleziono digirente Zio Paperone come username,
vorrei ottenere come risultato questo elenco:
Paperino
Qui
Quo
Qua
Nonnma Papera
Ciccio.
L'ordine non ha importanza.
Ora faccio così:

declare @IdPrincipale as int

set @IdPrincipale = (select Id from Utenti where UserName = 'Zio Paperone')

select Id, UserName, IdResponsabile from Utenti where IdResponsabile = @IdPrincipale

così ottengo questa lista:
Paperino
Nonna Papera

come faccio ad estrarre i loro subordinati (ipotizzando sottolivelli fino all'infinito)? ho provato ad impostare while con exists varie...ma non ottengo nulla,
perchè non so come si fa.
qualcuno mi può aiutare?
grazie
Paola
Modificato da paolagumi il 09 dicembre 2013 11.14 -
1.976 messaggi dal 27 luglio 2005
Contributi
salve Paola,
quello che devi fare e' utilizzare una query ricorsiva ( http://technet.microsoft.com/it-it/library/cc645516.aspx )...

in questo modo puoi "agganciare" il "responsabile" e percorrere tutto l'albero che lo collega ricorsivamente ai suoi sottoposti...
ad esempio
SET NOCOUNT ON;
USE tempdb;
GO
CREATE TABLE dbo.Utenti (
  Id int NOT NULL PRIMARY KEY,
  UserName varchar(10),
  IdResponsabile int NULL
  );
GO
INSERT INTO dbo.Utenti
  VALUES ( 1, 'Disney', NULL);

INSERT INTO dbo.Utenti
  VALUES (2, 'Paperone', 1);

INSERT INTO dbo.Utenti
  VALUES (4, 'Topolino', 1);

INSERT INTO dbo.Utenti
  VALUES (3, 'Pippo', 1);


INSERT INTO dbo.Utenti
  VALUES (5, 'Paperino', 2);

INSERT INTO dbo.Utenti
  VALUES (6, 'Qui', 5);

INSERT INTO dbo.Utenti
  VALUES (7, 'Pluto', 2);
GO
DECLARE @Resp int = 1;
WITH cte AS (
  SELECT u.Id, u.UserName, u.IdResponsabile
    , 1 AS lvl
    , CAST(Id AS VARBINARY(900)) AS [ordinamento]
    FROM dbo.Utenti u
    WHERE u.Id = @Resp
  UNION ALL
  SELECT u.Id, u.UserName, u.IdResponsabile
    , c.lvl +1
    , CAST(c.ordinamento + CAST(u.Id AS VARBINARY(4)) AS VARBINARY(900)) AS [ordinamento]
    FROM cte c 
      JOIN dbo.Utenti u ON u.IdResponsabile = c.Id
  )
  SELECT CAST( REPLICATE('|', lvl) AS varchar(5)) AS [Albero]
    , cte.Id, cte.UserName
    FROM cte
    ORDER BY ordinamento;
GO
DROP TABLE dbo.Utenti;
--<-----
Albero Id          UserName
------ ----------- ----------
|      1           Disney
||     2           Paperone
|||    5           Paperino
||||   6           Qui
|||    7           Pluto
||     3           Pippo
||     4           Topolino


come indicato sia nell'esempio che nella sinossi dell'espressione, puoi aggiungere un attributo "livello" alla selezione che ti ritorna la profondita' di ogni riga rispetto al responsabile indicato nella ricerca, e con questo, ad esempio, ottenere una rappresentazione ad "albero" della stessa profondita'...

vedi anche l'opzione MAX RECURSION n, che di base ha un valore pari a 100, e nel caso tu abbia una profondita' effettiva superiore a questo valore, devi manualmente impostare al massimo livello di profondita' al fine di recuperare tutte le righe...
saluti

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.