1

Okay people, I have half solved my problem and I believe I need help solving the other half. I was able to stuff several rows of data from one column (TEAMS) and concatenate into one column, however, it appears that I need to do the same thing to another column within the same data set.

Here is the current data set example:

FIRST | LAST      | YEAR  | ID  | TEAMS
-- -- -- -- -- -- -- -- -- -- -- -- -- 
Chris | Anderson  | 2015  | 176 | 05 White (B)
Chris | Anderson  | 2016  | 176 | 05 Royal (B)
Chris | Anderson  | 2017  | 176 | 05 Royal (B), '08 Gray (B)
Chris | Anderson  | 2018  | 176 | 05 Royal (B), 08 (B)

What I need is to have the year VALUE as the column name and the teams data as the VALUE, like this:

FIRST | LAST     | 2015         | 2016         | 2017
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
Chris | Anderson | 05 White (B) | 05 Royal (B) | 05 Royal (B), '08 Gray (B)

Here is my existing SQL statement that produces the current (first) data set.

SELECT DISTINCT TOP 100 PERCENT dbo.Coaches.FirstName, dbo.Coaches.LastName, dbo.Teams.clubYear, dbo.Coaches.CoachID,
STUFF ((   SELECT  ', '+ SUBSTRING(TeamName,14,len(TeamName)) + ' ('+LEFT(gender,1)+')'
         FROM     dbo.Teams ST
         WHERE    ST.CoachID = dbo.Coaches.CoachID AND ST.clubYear = dbo.Teams.clubYear
         ORDER BY clubYear, CoachID
         FOR XML PATH('')), 1, 1, '') AS Teams FROM    dbo.Coaches INNER JOIN
    dbo.Teams  ON dbo.Coaches.CoachID = dbo.Teams.CoachID
WHERE   dbo.teams.teamTypeID = 3
GROUP BY dbo.Coaches.FirstName, dbo.Coaches.LastName, dbo.Teams.clubYear, dbo.Teams.TeamName, dbo.Coaches.CoachID
ORDER BY dbo.Coaches.LastName, dbo.Coaches.FirstName, dbo.Teams.clubYear
James A Mohler
  • 11,060
  • 15
  • 46
  • 72
David Jacobson
  • 169
  • 2
  • 11
  • 2
    What version of SQL Server? Posting a sample of the results is very helpful. Since it's not CF specific, care to throw it into a http://sqlfiddle.com/? :-) That makes it a lot easier for others to collaborate and help you find an answer. – SOS Sep 27 '18 at 21:33
  • 2
    Looks like a PIVOT table problem. – James A Mohler Sep 27 '18 at 22:03

1 Answers1

3

If the current data set example is the result of your statement, this should be rather easy. I'll mock-up your query by creating a similar dataset within a declared table variable. Just replace the SELECT * FROM @tbl with your statement.

DECLARE @tbl TABLE ([FIRST] VARCHAR(100),[YEAR] INT,TEAMS VARCHAR(100));
INSERT INTO @tbl VALUES
 ('Chris',2015,'White (B)')
,('Chris',2016,'05 Royal (B)')
,('Chris',2017,'05 Royal (B), 08 Gray (B)');

--The query will use your dataset and send it into PIVOT

SELECT p.*
FROM
(
    SELECT * FROM @tbl
) t
PIVOT
(
    MAX(TEAMS) FOR [YEAR] IN([2015],[2016],[2017])
) p;

The result

FIRST   2015        2016            2017
Chris   White (B)   05 Royal (B)    05 Royal (B), 08 Gray (B)
Shnugo
  • 66,100
  • 9
  • 53
  • 114
  • Shnugo, that is awesome, THANK YOU SO MUCH!! It works exactly as I wanted, however, I have a quick question. The [YEARS] are dynamic as some may have teams from 2009 through 2018 and forward and others will not. How could I update the query to reflect that? – David Jacobson Sep 28 '18 at 15:54
  • Unfortunately PIVOT doesn't support dynamic names. It requires dynamic sql. Just be sure to read the posts about avoiding SQL injection. https://stackoverflow.com/questions/1439403/sql-server-dynamic-pivot-table-sql-injection and https://stackoverflow.com/search?q=%5Bsql-server%5D+dynamic+pivot – SOS Sep 28 '18 at 20:40
  • 1
    @DavidJacobson The columns of a resultset must be known in advance. There are two approaches: Add all possible years to the `IN` list. This will return the same set in any case, but it will return `NULL` values if there are no values. The other chance is *dynamic SQL* like suggested by Ageax. The question is: How are you consuming this query? Is it for some kind of report? Is there a presentation layer in between? Humany eyes wouldn't like *empty* years, while an application would not like unpredictable column names... – Shnugo Sep 30 '18 at 10:13