直接上题目:

注释:其中 name是人员名称 id 是地点编号,
因为 a 即在1 地点 又在2 地点 还在 5 地点 ,因此 1 2 5地点的所有人需要合并成一个集合,因为b即在 1 地点 又在 3 地点, 所以3地点的人员也要和前面3个地点人员合并 ,最终 1 2 3 5 人员是一个集合
同理,因为 i在 7 又在 4 所以 4 和 7 是一个集合
最后,z 只在 6 地点有,因此 6地点只有一个元素 z
最终结果是这样的:

其中过程大概就是这样

代码如下:
with ts as(select 'a' as p_name, 1 as p_idfrom dualunion allselect 'b', 1from dualunion allselect 'c', 1from dualunion allselect 'a', 2from dualunion allselect 'd', 2from dualunion allselect 'e', 2from dualunion allselect 'b', 3from dualunion allselect 'f', 3from dualunion allselect 'k', 4from dualunion allselect 'i', 7from dualunion allselect 'i', 4from dualunion allselect 'j', 4from dualunion allselect 'a', 5from dualunion allselect 'p', 5from dualunion allselect 'q', 5from dualunion allselect 'z', 6 from dual),ts1 as --将有关系的人的名称进行一一对应 ,并规定小的为父 大的为子,形成单向树状结构(select distinct least(t1.p_name, t2.p_name) as fu,greatest(t1.p_name, t2.p_name) as zifrom ts t1inner join ts t2on t1.p_id = t2.p_idand t1.p_name <> t2.p_name),ts2(zi,max_fu) as --将所有顶级父节点按照树状结构进行单向搜索(select zi, fu as max_fu --将顶级父节点记录下来 方便后面分组from ts1where fu in (select fu --此条件可筛选出此方向的顶级父节点 但不包含单个节点from ts1minusselect zi from ts1)union allselect t1.zi, t2.max_fu from ts1 t1 inner join ts2 t2 on t1.fu = t2.zi),ts3 as --将所有与顶级父节点有关的所有子节点 和 父节点 本身 以及 单个节点 进行合并(select max_fu, zifrom ts2unionselect distinct p_name, p_namefrom tswhere p_name not in (select zi from ts1)) --此条件可筛选出所有的顶级父节点和单个节点select listagg(zi, ',') within group(order by zi) as flag ---将所有子节点 和父节点 按照顶级父节点分组 并且合并成一行from ts3group by max_fu
感觉还不错的话,点下在看鼓励一下作者吧 
没有关注的也可以关注下公众号~再次感谢



最后修改时间:2021-04-19 17:16:39
文章转载自SQL大数据开发,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




