conectarse dando antes resultados incorrectos

Assume I have 2 tables as shown below – PARENT and CHILD

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');

The output has to be something like below:

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

I have written the below query to achieve this. I don't know where it is going wrong, query seems to be fine but the output is not what is desired.

Please help me out as I am almost saturated debugging this.

select parent_id, parent_name, substr(max(sys_connect_by_path(child_name, ',')),2) 
( 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 

preguntado el 28 de mayo de 14 a las 11:05

Anyone good at hierarchical queries please help me out. -

2 Respuestas

You don't see hierartical data. It is simple master detail.

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' is not connected because it parent_id is 3.

Hm... listagg is a 11g feature. The general solution before 11g was to use Tom Kyte's aproach:

Y echa un vistazo a for performance expectations

Ok, let's continue with "connect by" aproach. First of all, lets reduce complexity by forgetting about parent table. We will be building right side of left outer join query above, but using connect by construction.

Second, I think you missed how parent_id and child_id are named. My guess is that your child_id is actually your parent_id in parent table. So name is wrong.

3 conditions to put all children in a row:

  1. All children have the same child_id (parent.parent_id)

  2. first one has parent_id = 1 (more like order_id)

  3. every next one has parent_id +1 comparing to previous one

Let's put it all into query:

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

Then you add your SYS_CONNECT_BY_PATH(name, ', '), get the last element and only then join it with parent table, but based on parent.parent_id = children.child_id

contestado el 29 de mayo de 14 a las 15:05

Thanks VAV for the listagg function. But i use Oracle 10g and wanted to know what is wrong with the sys_connect_by_path function used. I get a wrong output somehow. Query seems to be fine, not sure if i missed out anything in the query? Pls help.. - user3682879

here is your query after correction, actually you did some mistake in column name of children table(wrote ch.child_name while it is or name)

select parent_id, parent_name,cnt,substr(max(sys_connect_by_path(child_name, ',')),2) child_name
( select p.parent_id, p.parent_name, p.cnt , child_name, row_number() over (partition by p.parent_id, p.parent_name order by 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  

Respondido el 04 de junio de 14 a las 13:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.