Reputation: 4202
I am trying to write a sub-query, that stores all the results in a single column separated by a comma. My code looks something like this
SELECT column1,
column2,
CourseRequests=(SELECT INNERCourseRequests =
COALESCE(CASE
WHEN innercourserequests
= '' THEN
crse_name
ELSE innercourserequests
+ ',' +
crse_name
END, '')
FROM tor_studentcrserequest SCR
WHERE SCR.stud_pk = MS.tt_stud_pk
AND SCR.delt_flag = 0),
column4
FROM tbl_mainstudent MS
When I try to execute the stored procedure, I get an error saying Invalid column name 'INNERCourseRequests'.
What is the correct way to do this? TSR is a reference to table from the outer column
EDIT: I changed it to:
CourseRequests=(SELECT INNERCourseRequests =
COALESCE(case when @INNERCourseRequests='' THEN CRSE_NAME ELSE
@INNERCourseRequests+','+CRSE_NAME end,'')
However, now I"m getting an error saying subquery returned more than 1 result
which is expected.
Upvotes: 0
Views: 393
Reputation: 48776
You can use FOR XML along with a few REPLACEs as shown here:
SELECT column1,
column2,
CourseRequests=COALESCE(
REPLACE(REPLACE(REPLACE((
SELECT crse_name
FROM (
SELECT 1, 22, 'first', 0
UNION ALL SELECT 2, 22, 'second', 1
UNION ALL SELECT 3, 22, 'third', 0
UNION ALL SELECT 4, 555, 'first', 1
) SCR (id, stud_pk, crse_name, delt_flag)
WHERE SCR.stud_pk = MS.tt_stud_pk
AND SCR.delt_flag = 0
FOR XML PATH('')
),'</crse_name><crse_name>', ','),
'</crse_name>', ''), -- remove end tag
'<crse_name>', ''), -- remove beginning tag
''), -- optional COALESCE to ensure no NULLs
column4
FROM (
SELECT 1, 'a', 'b', '2014-01-01'
UNION ALL SELECT 22, 'd', 'e', '2014-02-02'
) MS (tt_stud_pk, column1, column2, column4)
Output:
column1 column2 CourseRequests column4
a b 2014-01-01
d e first,third 2014-02-02
Explanation:
The FOR XML PATH('') flattens the result of the sub-query to be:
<crse_name>first</crse_name><crse_name>third</crse_name>
Note:
There might be a slightly more elegant way to do the XML stuff so you don't need all of the REPLACEs, but not sure and this does work.
Upvotes: 1
Reputation: 40289
I'm pretty sure you can't do this with a single query, and I'm not entirely certain the tactic I've come up with is a legitimate tactic--meaning, if it is undocumented, a future version of SQL might not support this. With that said:
Start with the following:
DECLARE @List varchar(max)
SELECT @List = isnull(@List + ', ', '') + InnerCourseRequests
from tor_studentcrserequest
where stud_pk = <TestValue>
and delt_flag = 0
PRINT @List
This will generate a comma-delimited list of all InnerCourseRequests from the tor_studentcrserequest table for a single stud_pk.
Next, turn it into a function:
DROP FUNCTION phkTest
GO
CREATE FUNCTION phkTest (@stud_pk int) -- Change datatype, if not int
RETURNS varchar(max)
AS
BEGIN
DECLARE @List varchar(max)
SELECT @List = isnull(@List + ', ', '') + InnerCourseRequests
from tor_studentcrserequest
where stud_pk = @stud_pk
and delt_flag = 0
RETURN @List
END
GO
(Add a second parameter for delt_flag, if that might vary somehow)
And add that to a query:
SELECT distinct tt_stud_pk, dbo.phkTest(stud_pk)
from tbl_mainstudent
(I wrote all this using one of my tables, then cut-and-paste your table/columns in, so there may be some syntax issues to deal with.)
There may be ways to improve performance for big tables (OUTER APPLY
, select distinct before calling the function, and so forth), and it's entirly likely that this might best be done via procedural code by whatever's querying the data in the first place.
Upvotes: 0