通过事先给出错误的结果连接

时间:2014-05-28 10:53:53

标签: oracle oracle10g hierarchical-data

假设我有2个表,如下所示 - 父母和孩子

create table parent
(
parent_id   number,
parent_name varchar2(10),
cnt         number
)

create table children
(
child_id   number,
parent_id  number,
name       varchar2(10)
)

insert into parent values (1, 'A', 3);
insert into parent values (2, 'B', 2);

insert into children values (1, 1, 'AB'); 
insert into children values (1, 2, 'AC'); 
insert into children values (1, 3, 'AD'); 
insert into children values (2, 1, 'BA'); 
insert into children values (2, 2, 'BB');

输出必须如下所示:

Parent_ID   Parent_Name Cnt Child_Names
1             A           3 AB, AC, AD
2             B           2 BA, BB

我已经编写了以下查询来实现这一目标。我不知道它出错的地方,查询似乎很好,但输出并不是我想要的。

请帮帮我,因为我几乎已经饱和地调试了这个。

select parent_id, parent_name, substr(max(sys_connect_by_path(child_name, ',')),2) 
from 
( select p.parent_id, p.parent_name, ch.child_name, row_number() over (partition by p.parent_id, p.parent_name order by ch.child_name) rn 
  from parent p, children ch 
  where p.parent_id = ch.parent_id
)
start with rn =1
connect by prior rn+1 = rn
group by parent_id, parent_name 

2 个答案:

答案 0 :(得分:0)

您不会看到层次数据。这是一个简单的主要细节。

select p.parent_id, p.parent_name, p.cnt, c.children_names, c.real_count
from parent p left outer join
(select parent_id, listagg(name, ', ') within group (order by name) children_names,
count(*) real_count from children group by parent_id) c
on p.parent_id = c.parent_id

' AD'没有连接,因为它的parent_id是3。

Hm ... listagg是一个11g的功能。 11g之前的一般解决方案是使用Tom Kyte的方法: http://www.sqlsnippets.com/en/topic-11591.html

并查看http://www.oracle-developer.net/display.php?id=515的表现期望

好的,让我们继续"通过"的形式给出。 首先,让我们忘记父表来降低复杂性。我们将构建上面左外连接查询的右侧,但是通过构造使用连接。

其次,我认为你错过了parent_id和child_id的命名方式。我的猜测是你的child_id实际上是父表中的parent_id。所以名字是错的。

将所有孩子排成一排的3个条件:

  1. 所有孩子都有相同的child_id(parent.parent_id)

  2. 第一个有parent_id = 1(更像是order_id)

  3. 每个下一个都有parent_id +1与前一个

  4. 相比

    让我们全部查询:

    select c.*, level  from children c
    start with parent_id = 1 --2nd condition 
    connect by prior 
    c.parent_id = c.parent_id -1 --3rd condition
    and prior child_id = child_id --1st condition
    order by child_id, parent_id
    

    然后添加SYS_CONNECT_BY_PATH(名称,','),获取最后一个元素,然后将其与父表连接,但基于parent.parent_id = children.child_id

答案 1 :(得分:0)

这是你的修正后的查询,实际上你在子表的列名中做了一些错误(写了ch.child_name,而它是ch.name或name)

select parent_id, parent_name,cnt,substr(max(sys_connect_by_path(child_name, ',')),2) child_name
from 
( select p.parent_id, p.parent_name, p.cnt , ch.name child_name, row_number() over (partition by p.parent_id, p.parent_name order by ch.name) rn 
  from parent p, children ch 
  where p.parent_id = ch.parent_id
)
start with rn =1
connect by prior rn+1 = rn
group by parent_name,cnt,parent_id