2017-04-13 42 views
2

我有有在最高5級獲取第n層上自引用表

groupid | parentid | detail 
--------- | --------- | --------- 
Group A | Highest | nope 
Group B | Group A | i need this 
Highest | NULL  | nope 
Group C | Group B | nope 
Group D | Group C | nope 

我有查找到桌子上的GROUPID交易臺上方檢索細節值自引用表其中groupid = B組。事務表上groupid的值僅在B組到D之間,並且永遠不會更高。

txnid  | groupid | desired | desired 
--------- | --------- | --------- | --------- 
1   | Group D | Group B | i need this 
2   | Group B | Group B | i need this 
3   | Group C | Group B | i need this 
4   | Group B | Group B | i need this 

我的T-SQL腳本應該如何獲得所需的列?我可以多次離開加入自引用表,直到B組與我需要加入的時間不一致爲止。

非常感謝您的任何想法!

+0

爲什麼停在'A組'以及'desired'列的目的是什麼? –

+0

你知道交易表上每個groupid的等級嗎? – McNets

+0

@TimBiegeleisen它是公司級別的層次結構。例如:最高 - 公司,A組 - 部門,B組 - 部門,C組 - 團隊,D組 - 個人。道歉,如果它令人困惑,因爲我必須掩蓋實際的表示。在我的例子中,期望的列應該是部門的價值。我需要將它存儲在交易表中,以便稍後在交易表中應用子集/行級權限。 – mtryingtocode

回答

0

我還不清楚你怎麼知道哪個是B組,我想它是父母的父母爲空的記錄。

create table org(groupid char(1), parentid char(1), details varchar(20)); 
insert into org values 
('a', null, 'nope'),('b', 'a', 'I need this'),('c', 'b', 'nope'),('d', 'c', 'nope'),('e', 'd', 'nope'); 

create table trans(id int, groupid char(1)); 
insert into trans values 
(1, 'b'),(2, 'c'),(3, 'c'),(4, 'd'),(5, 'e'); 
GO 
 
10 rows affected 
with all_levels as 
(
    select  ob.groupid groupid_b, oc.groupid groupid_c, 
       od.groupid groupid_d, oe.groupid groupid_e, 
       ob.details 
    from  org ob 
    inner join org oc 
    on   oc.parentid = ob.groupid 
    inner join org od 
    on   od.parentid = oc.groupid 
    inner join org oe 
    on   oe.parentid = od.groupid 
    where  ob.parentid is not null 
) select * from all_levels; 

GO 
 
groupid_b | groupid_c | groupid_d | groupid_e | details  
:-------- | :-------- | :-------- | :-------- | :---------- 
b   | c   | d   | e   | I need this 
--= build a 4 levels row 
with all_levels as 
(
    select  ob.groupid groupid_b, oc.groupid groupid_c, 
       od.groupid groupid_d, oe.groupid groupid_e, 
       ob.details 
    from  org ob 
    inner join org oc 
    on   oc.parentid = ob.groupid 
    inner join org od 
    on   od.parentid = oc.groupid 
    inner join org oe 
    on   oe.parentid = od.groupid 
    where  ob.parentid is not null 
) 
    --= no matter what groupid returns b group details 
    , only_b as 
    (
     select groupid_b as groupid, groupid_b, details from all_levels 
     union all 
     select groupid_c as groupid, groupid_b, details from all_levels 
     union all 
     select groupid_d as groupid, groupid_b, details from all_levels 
     union all 
     select groupid_e as groupid, groupid_b, details from all_levels 
    ) 
    --= join with transactions table 
    select  id, t.groupid, groupid_b, ob.details 
    from  trans t 
    inner join only_b ob 
    on   ob.groupid = t.groupid; 
GO 
 
id | groupid | groupid_b | details  
-: | :------ | :-------- | :---------- 
1 | b  | b   | I need this 
2 | c  | b   | I need this 
3 | c  | b   | I need this 
4 | d  | b   | I need this 
5 | e  | b   | I need this 

dbfiddle here

您可以處理遞歸函數太多,但我不相信它可以在性能方面更好。

create function findDetails(@groupid char(1)) 
returns varchar(100) 
as 
begin 
    declare @parentid char(1) = '1'; 
    declare @next_parentid char(1) = '1'; 
    declare @details varchar(100) = ''; 

    while @next_parentid is not null 
    begin 
     select  @details = org.details, @parentid = org.parentid, @next_parentid = op.parentid 
     from  org 
     inner join org op 
     on   op.groupid = org.parentid 
     where  org.groupid = @groupid 

     set @groupid = @parentid; 
    end 

    return @details; 
end 
GO 
select id, groupid, dbo.findDetails(groupid) as details_b 
from trans; 
GO 
 
id | groupid | details_b 
-: | :------ | :---------- 
1 | b  | I need this 
2 | c  | I need this 
3 | c  | I need this 
4 | d  | I need this 
5 | e  | I need this 

dbfiddle here