Биты и байты.

Биты и байты.

вторник, 3 декабря 2013 г.

Будь выше любых иерархий!

Везде куда  не глянь, есть иерархии,  в армии, на работе, в жизни и быту,
так уж устроен мир одни управляют другими……


Допустим нужно вывести иерархический справочник в виде списка чтобы визуально было понятно кто кому зачем и почему)
для этого нужна простая иерархия родитель-потомок, построим на примере сотрудников, здесь ID потомок, MgrID родитель.
Самыми главными будем считать тех у кого нет босов т. е  WHERE MgrID IS NULL


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)
            ,CAST(Name as VARCHAR(255)) as orderSequence
    FROM Employee
    WHERE MgrID IS NULL

    UNION ALL
    --  Recursive query
    SELECT   E.ID
            ,E.Name
            ,E.MgrID
            ,H.nLevel+1
            ,Family
            ,CAST(H.orderSequence + '\' + E.Name as VARCHAR(255))
    FROM Employee   E
    JOIN Hierarchy  H ON E.MgrID = H.ID
)
SELECT H.*,replicate(' ',nLevel*5)+Name as Hname
FROM Hierarchy H
ORDER BY orderSequence

Вот вам и готовый результат


В дополнение как избежать циклов  в графах при поиске путей

drop table if exists #hier
create table  #hier
(
    id int identity(1,1),
    parent int null,
    child int null
    )
 insert into #hier
    select null,1
    union
    select 1,2
        union
    select 1,3
        union
    select 2,4
        union
    select 3,5
        union
    select 2,6
        union
    select 4,1
   
;with hierarchy
as
(
select
child, parent, 0 as cycle,
CAST('.' as varchar(max)) + LTRIM(child) + '.' as [path]
from #hier
where parent is null
union all
select
c.child,c.parent,case when p.[path] like  '%.' + LTRIM(c.child) + '.%' then 1 else 0 end as cycle,
p.[path] + LTRIM(c.child) + '.' as [path]
from
hierarchy as p
inner join #hier as c on p.child = c.parent
and p.cycle = 0
)
select
child,parent,[path],cycle from
hierarchy h
--where  h.path like '%.1104.%.1031.%'


И наконец немного юмора

Девушка на свидании спрашивает у парня: — Вась, а ты до меня за кем-нибудь ухаживал? — Да, в деревне за скотиной...

About