views:

3043

answers:

8

For example I have two tables. The first table is student while the second table are the courses that the a student is taking. How can I use a select statement so that I can see two columns student and courses so that the courses are separated by commas.

Thanks.

A: 

It depends on which server you're using. SQL Server? MySQL? Other?

Joel Coehoorn
A: 

I am using SQL Server.

A: 

Generally, what you're talking about is a join:

SELECT 
    S.*,
    SC.*
  FROM
    Students S
    INNER JOIN Student_Courses SC
      ON S.student_id = SC.student_id

However, that will give you one row per course. SQL doesn't make it easy to get the set of courses as a comma delimited list in a single row (that's not a set-based operation). Depending on the vendor, there are different ways to do it, involving looping.

Ian Varley
A: 

I think this MySQL page will help you with that. http://dev.mysql.com/doc/refman/4.1/en/group-by-modifiers.html

hash
A: 

So you want to see:

'Jade', 'Math, English, History'
'Kieveli', 'History, Biology, Physics'

Yes, comma separated is always desirable, but SQL isn't good at it. Here's the approach I was always planning on using:

Create a Function on the SQL server that uses a cursor to loop over the subquery (sorry - I didn't fully test this):

CREATE FUNCTION commacourselist(@studentname varchar(100))
RETURNS @List varchar(4096)
AS
BEGIN

DECLARE @coursename varchar(100)

DECLARE FOR
SELECT course.name FROM course WHERE course.studentname = @studentname
OPEN coursecursor

FETCH NEXT FROM coursecursor INTO @coursename 
WHILE @@FETCH_STATUS = 0
BEGIN
 IF @List = ''
 BEGIN
  SET @List = @coursename
 END
 ELSE
 BEGIN
  SET @List = @List + ',' + @coursename 
 END
 FETCH NEXT FROM coursecursor INTO @coursename 
END
CLOSE coursecursor 
DEALLOCATE coursecursor 

RETURN
END
GO

Then Call the function in the query:

SELECT student.name, commacourselist( student.name ) FROM student

Kieveli
Thanks I'll try this out tomorrow. Thanks
A cursor? No! 2005's PIVOT could probably be used for this, or a custom aggregate, or the Stuff() option below, or just about _anything_ but a cursor.
Joel Coehoorn
Joel - do you have an example of how to use PIVOT for this? I tried to figure that method out, but I couldn't wrap my head around it.
BenAlabaster
I saw a vague reference on how to COALESCE() to a string list, but couldn't find any concrete implementation. I've done some PIVOTs before, and never did they show promise of creating a comma separated list.
Kieveli
The PIVOT will give you one column for the studentname and one column for each course (variable non-null columns for each row). You were asking for two columns, so a pivot won't exactly work.
Kieveli
Try out the Stuff and see if it works.
Kieveli
@Kieveli: Coalesce() is great if you've got multiple columns and you want to concatenate them to a single column, but not so great if you want to concatenate multiple rows to a single.
BenAlabaster
A: 

You can use a UDF that cursors through the related records and concats a return string together but this will be expensive - if you give it a go make sure your cursor is READ_ONLY FAST_FORWARD

Rich Andrews
A: 

Are you using 2005 or 2008? If so, then lookup the PIVOT comand. It should be more efficient than a function with a cursor.

HLGEM
+3  A: 

Assuming you're using SQL Server 2005:

This should do what you're after - obviously replace fields as you need:

For demo purposes, consider the following two table structures:

Students(
  STU_PKEY Int Identity(1,1) Constraint PK_Students_StuPKey Primary Key,
  STU_NAME nvarchar(64)
)

Courses(
  CRS_PKEY Int Identity(1, 1) Constraint PK_Courses_CrsPKey Primary Key,
  STU_KEY Int Constraint FK_Students_StuPKey Foreign Key References Students(STU_PKEY),
  CRS_NAME nvarchar(64)
)

Now this query should do the job you're after:

Select  s.STU_PKEY, s.STU_NAME As Student,
     Stuff((
      Select ',' + c.CRS_NAME
      From Courses c
      Where s.STU_PKEY = c.STU_KEY
      For  XML Path('')
     ), 1, 1, '') As Courses 
From    Students s
Group By s.STU_PKEY, s.STU_NAME

Way simpler than the currently accepted answer...

BenAlabaster
If this works, it's magic.
Kieveli
Thanks I used this one and your right it is simple. Thanks :)
Magic I tells ya!!
Kieveli