Вы должны быть в состоянии сделать это, используя функцию SYS_CONNECT_BY_PATH.Для вашего примера должно работать что-то вроде следующего:
select
stud_no,
stud_name,
substr(SYS_CONNECT_BY_PATH(class_name, ', '),2) classes
from
(
select
cn.stud_no,
sn.stud_name,
cn.class_name,
count(*) OVER ( partition by cn.stud_no ) cnt,
ROW_NUMBER () OVER ( partition by cn.stud_no order by cn.class_name) seq
from
class_name cn
,stud_name sn
where
sn.stud_no = cn.stud_no
group by cn.stud_no, sn.stud_name, cn.class_name)
where
seq=cnt
start with
seq=1
connect by prior
seq+1=seq
and prior
stud_no=stud_no;
Чтобы разбить это на части ...
Внутренний запрос
select
sn.stud_no,
sn.stud_name,
cn.class_name,
count(*) OVER ( partition by cn.stud_no ) cnt,
ROW_NUMBER () OVER ( partition by cn.stud_no order by cn.class_name) seq
from
class_name cn
,stud_name sn
where
sn.stud_no = cn.stud_no
group by cn.stud_no, sn.stud_name, cn.class_name
даст набор результатовнапример:
STUD_NO STUD_NAME CLASS_NAME CNT SEQ
001 SAM CHEMISTRY 2 1
001 SAM PHYSICS 2 2
002 MICHAEL ART 3 1
002 MICHAEL HISTORY 3 2
002 MICHAEL PHYSICS 3 3
Обратите внимание, что набор результатов упорядочен таким образом, что записи классов для каждого учащегося сгруппированы в соответствии с stud_no.CNT указывает общее количество записей в группе (разделе), к которой принадлежит запись (включая общее количество всех записей с одинаковым stud_no), а SEQ указывает уникальную последовательность / ранг в этой группе (в данном случае на основев алфавитном порядке по имени класса).
Затем оставшаяся часть запроса строит список имен классов, разделенных запятыми, для каждого учащегося путем обхода результирующего набора с использованием значений CNT и SEQ следующим образом:
substr(SYS_CONNECT_BY_PATH(class_name, ', '),2) classes
-- builds a list of class names separated by a comma
-- (the substr function is just there to remove the first delimiter)
where seq=cnt -- this condition indicates the last record in each group/list
start with seq=1
-- the starting point for each group (i.e. start a new list every time a seq
-- value of 1 is encountered while traversing the result set)
connect by prior seq+1=seq and prior stud_no=stud_no
-- defines the connection between one list element and the next; the next
-- element in a list will have the same stud_no as the prior element AND a
-- seq equal to the prior element's seq +1
Результат:
STUD_NO STUD_NAME CLASSES
001 SAM CHEMISTRY, PHYSICS
002 MICHAEL ART, HISTORY, PHYSICS
Этот подход и несколько других возможных вариантов описаны здесь: http://www.dba -oracle.com / t_converting_rows_columns.htm
Надеюсь, это поможет!