You should be able to do this using the SYS_CONNECT_BY_PATH function. For your example, something like the following should work:
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;
To break this down...
The inner query
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
will give a result set like this:
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
Note that the result set is ordered so that the class records for each student are grouped together according to stud_no. CNT indicates the total number of records in the group (partition) to which the record belongs (by including the total count of all records with the same stud_no), and SEQ indicates a unique sequence/rank within that group (in this case, based on an alphabetic ordering by class name).
The rest of the query then builds a list of comma-delimited class names for each student by traversing the result set using the CNT and SEQ values as follows:
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
The result:
STUD_NO STUD_NAME CLASSES
001 SAM CHEMISTRY, PHYSICS
002 MICHAEL ART, HISTORY, PHYSICS
This approach and a few other possible options are described here: http://www.dba-oracle.com/t_converting_rows_columns.htm
Hope that helps!