我有一个自我引用表,最多有5个级别
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 = Group 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 :(得分:0)
我还不清楚你怎么知道什么是GROUP 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