Sql 通过group by标识根节点

Sql 通过group by标识根节点,sql,oracle,group-by,hierarchical-data,hierarchical-query,Sql,Oracle,Group By,Hierarchical Data,Hierarchical Query,我需要在主通道的层次结构下只设置一组标志来标识主通道(层次结构中最高的)。在下面的情况下,US不是有效的主通道,因为下面有两个标志。唯一有效的主要频道是US1、US2、英国 如果可能的话,我希望有一个单一查询的解决方案;否则,我将探索程序选项 我尝试了一些分层查询、分组、计数(标志)的变体,但不知何故,我无法消除“我们”并获得所需的结果 如果有人能为这个用例提供高级方法,我将不胜感激 输入数据 --------------------------------- channel | flag |

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

如果可能的话,我希望有一个单一查询的解决方案;否则,我将探索程序选项

我尝试了一些分层查询、分组、计数(标志)的变体,但不知何故,我无法消除“我们”并获得所需的结果

如果有人能为这个用例提供高级方法,我将不胜感激

输入数据

---------------------------------
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   
----------------
使用输入数据进行标志计数的多个层次结构

---------------------------------
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
---------------------------------

这有点棘手。。。除非我错过了一条明显的捷径当然

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

内部查询是一个相当简单的分层查询,从三个
标志='yes'
行向上遍历树,除了这一点之外,它还分析每个
频道在生成的层次结构中出现的次数

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
实际上只在您的
输入数据中出现一次
;但是如果它存在两次,那么这仍然有效,中间计数只是4而不是2。你可以在中看到这个版本。

为什么US1和US2都属于我们,而它们又是“层次最高的”?除掉我们并包括英国似乎没问题,但我不明白最终结果中如何包括US1和US2?您两次将我们列为根节点(没有父节点),这也让人困惑。请参阅编辑,我已添加了中间结果集。您会注意到,通过使用输入数据,我们可以创建具有underflag count的多个层次结构。主通道应该是只有一个标志计数的通道,并且应该是层次结构中最高的通道。是的,删除了重复的美国条目。