There are several different ways of approaching this. The simplest is presentational: solve it in the front end display. In SQL*Plus that would be the BREAK keyword:
SQL> BREAK ON courseid ON coursename SQL> SQL> select c.courseid 2 , c.coursename 3 , s.studentname 4 from courses c 5 join course_students cs 6 on ( cs.courseid = c.courseid ) 7 join students s 8 on ( s.studentid = cs.studentid ) 9 / COURSEID COURSENAME STUDENTNAME ---------- ---------- -------------------- 1 math john smith jack jackson john jackson 2 english michael thomas jane doe SQL>
Another approach is to use an embedded cursor:
SQL> select c.courseid 2 , c.coursename 3 , cursor (select s.studentname 4 from course_students cs 5 join students s 6 on ( s.studentid = cs.studentid ) 7 where cs.courseid = c.courseid 8 ) 9 from courses c 10 / COURSEID COURSENAME CURSOR(SELECTS.STUDE ---------- ---------- -------------------- 1 math CURSOR STATEMENT : 3 CURSOR STATEMENT : 3 STUDENTNAME -------------------- john smith john jackson jack jackson 2 english CURSOR STATEMENT : 3 CURSOR STATEMENT : 3 STUDENTNAME -------------------- jane doe michael thomas SQL>
We can debate whether that truly counts as "a single row" :)
Finally we have string aggregation techniques. There are a number of different ways of slicing this particular cabbage, because - unbelievably - it wasn't until the very latest release that Oracle provided a standard built-in to do it. Because I'm not on 11gR2 I'll use WM_CONCAT() instead of LISTAGG():
SQL> select c.courseid 2 , c.coursename 3 , wm_concat(s.studentname) as studentnames 4 from courses c 5 join course_students cs 6 on ( cs.courseid = c.courseid ) 7 join students s 8 on ( s.studentid = cs.studentid ) 9 group by c.courseid 10 , c.coursename 11 / COURSEID COURSENAME STUDENTNAMES ---------- ---------- --------------------------------------------- 1 math john smith,john jackson,jack jackson 2 english jane doe,michael thomas SQL>
Tim Hall's Oracle-Base site has a round up of all of the string aggreation options. Find out more.
SELECT c.*, list FROM courses c, STRJOIN(select * from students where course_id=?,', ') listNULLif the previous row's value ofcourseidis the same as the current ones? Would your teacher be wanting you to uselag?