通过分组标识根节点

时间:2018-07-18 16:34:53

标签: sql oracle group-by hierarchical-data hierarchical-query

我需要标识主要通道(层次结构中最高),在其主要层次结构下仅设置一组标志。在下面的情况下,US不是有效的主要频道,因为下面有两个标志。只有有效的主要渠道是US1,US2和UK。

如果可能的话,我想用一个查询解决方案;否则,我将探讨程序的选项。

我尝试使用分层查询,分组依据,count(flag)进行了几种变体,以某种方式我无法消除“ US”并获得所需的结果。

如果有人可以为我提供高级方法,我将不胜感激。

输入数据

---------------------------------
channel | flag  | parent channel
---------------------------------
US      |       |               

US1     |       | US        
A1      | yes   | US1       
A2      |       | A1        
A3      |       | A2

US2     |       | US        
B1      |       | US2       
B2      | yes   | B1        
B3      |       | B2        

UK      |       |   
C1      |       | UK        
C2      |       | C1        
C3      | yes   | C2        
---------------------------------

使用输入数据的带有标记计数的多个层次结构

---------------------
channel | flag count 
---------------------
US      | 2     

US1     | 1     
A1      | 1 
A2      | 0      
A3      | 0      

US2     | 1     
B1      | 1      
B2      | 1   
B3      | 0      

UK      | 1      
C1      | 1      
C2      | 1      
C3      | 1   
----------------

输出

---------------------------------
primary channel
---------------------------------
US1
US2
UK
---------------------------------

1 个答案:

答案 0 :(得分:1)

这有点棘手...除非我当然缺少明显的捷径...

select max(channel) keep (dense_rank last order by lvl) as primary_channel
from (
  select channel, connect_by_root(channel) as root, level lvl,
    count(*) over (partition by channel) as flag_count
  from input_data
  connect by channel = prior parent_channel
  start with flag = 'yes'
)
where flag_count = 1
group by root;

PRIMARY_CHANNEL
---------------
US1
US2
UK

db<>fiddle demo.

内部查询是一个相当简单的层次查询,它从三行flag = 'yes'行中爬到树上,除了对每个channel出现的次数进行分析计数之外,生成了层次结构。

select channel, connect_by_root(channel) as root, level lvl,
  count(*) over (partition by channel) as flag_count
from input_data
connect by channel = prior parent_channel
start with flag = 'yes';

CHANNEL ROOT        LVL FLAG_COUNT
------- ---- ---------- ----------
A1      A1            1          1
B1      B2            2          1
B2      B2            1          1
C1      C3            3          1
C2      C3            2          1
C3      C3            1          1
UK      C3            4          1
US      A1            3          2
US      B2            4          2
US1     A1            2          1
US2     B2            3          1

11 rows selected. 

然后,外部查询将消除计数大于1的所有内容-即,两个US行;并使用另一个分析函数为结果中剩余的每个根查找具有最高级别的行。


我假设US实际上仅在您的input_data中出现一次;但是如果它存在两次,则仍然有效,中间计数仅为4而不是2。您可以在this db<>fiddle中看到该版本。