1

I have a table with the following results (from an SQL Query)

ID Type Comment
12345 Manager Comment This is a Manager comment
12345 HR Comment This is a HR comment
12345 HR Comment This is another HR comment
54321 Manager Comment This is a Manager comment
54321 Manager Comment This is another Manager comment
54321 Manager Comment This is another Manager comment aswell

I'm tryring to get the output to look like this:

ID Manager Comment 1 Manager Comment 2 Manager Comment 3 HR Comment 1 HR Comment 2
12345 This is a HR comment This is a HR comment This is another HR Comment
54321 This is a Manager comment This is another Manager comment This is another Manager comment aswell

This number of comments can be variable between 0 and 5.

I've tried the following but it only works on the newest comments in each section:

SELECT *
FROM
(
    SELECT
        A.[SHIFTASSIGNID] as 'ID'
        ,c.[COMMENTTEXT] as 'Comment Type'
        ,b.COMNTNOTETXT as 'Comment'

      FROM [tkcsdb].[dbo].[SHFTASGNCOMNTMM] A 
      join [tkcsdb].[dbo].[COMNTNOTEDTL] B on
      a.[COMNTNOTEID] = b.[COMNTNOTEID]

      join [tkcsdb].[dbo].[COMMENTS] C
      on c.commentID = a.commentID
        where A.SHIFTASSIGNID = 7354246
) AS SourceTable PIVOT(max([Comment]) FOR [Type] IN([HR Notes],[Manager Notes], [Kommentar])) AS PivotTable;

Obviously it won't accomodate multipe comments, I've spent about 3 hours on this at the minute so any help would be much appreciated.

Thanks Chris

eshirvana
  • 23,227
  • 3
  • 22
  • 38
Walshie1987
  • 443
  • 2
  • 6
  • 19
  • 1
    tag your database as well – eshirvana May 19 '21 at 16:35
  • I think you'd have to create a row_number column then concat the rownumber to the comment type field. If the number of comments is dynamic then you would need a dynamic pivot. I actually just answered a question on that. https://stackoverflow.com/questions/67580698/oracle-sql-converting-rows-into-columns-dynamically/67581190#67581190 – Michael Z. May 19 '21 at 16:36
  • Why are you trying to do this? *(If the number of comments is variable the structure most appropriate for use in SQL is the one you already have. If you're pivoting the data for presentation to a human, do that in your presentation layer / application, don't do it in SQL. This is a SQL Anti-Pattern / Code-Smell.)* – MatBailie May 19 '21 at 16:41

2 Answers2

0

See a working example at the end. In the example I give comments a date so that they can be sorted accordingly.

What I'm doing:

I'm adding a row number to each comment text, so that Manager Comment becomes Manager Comment 1 or Manager Comment 2 depending on the row number.

Then since we know we will have a max of five comments per type we can simply ask for all of them in the PIVOT

SELECT
  *
FROM (
  SELECT
    A.[SHIFTASSIGNID] AS 'ID'
   ,C.[COMMENTTEXT] + ' ' + CONVERT(NVARCHAR(20), ROW_NUMBER() OVER (PARTITION BY A.[SHIFTASSIGNID], C.[COMMENTTEXT] ORDER BY (SELECT NULL))) AS 'Comment Type'
   ,B.COMNTNOTETXT    AS 'Comment'

  FROM [tkcsdb].[dbo].[SHFTASGNCOMNTMM] A
  JOIN [tkcsdb].[dbo].[COMNTNOTEDTL] B
    ON A.[COMNTNOTEID] = B.[COMNTNOTEID]

  JOIN [tkcsdb].[dbo].[COMMENTS] C
    ON C.commentID = A.commentID
  WHERE
    A.SHIFTASSIGNID = 7354246
) AS SourceTable PIVOT (MAX([Comment]) FOR [Comment Type] IN ([Manager Comment 1], [Manager Comment 2], [Manager Comment 3], [Manager Comment 4], [Manager Comment 5], 
                                                      [HR Comment 1], [HR Comment 2], [HR Comment 3], [HR Comment 4], [HR Comment 5])) AS PivotTable;

Working Example:

SELECT
  12345                       AS 'ID'
 ,'Manager Comment'           AS 'Type'
 ,'This is a Manager comment' AS 'Comment'
 ,CONVERT(DATE, '2021-01-01') AS 'Date'
INTO #COMMENTS
UNION ALL
SELECT
  12345                       AS 'ID'
 ,'HR Comment'                AS 'Type'
 ,'This is a HR comment'      AS 'Comment'
 ,CONVERT(DATE, '2020-01-01') AS 'Date'
UNION ALL
SELECT
  12345                        AS 'ID'
 ,'HR Comment'                 AS 'Type'
 ,'This is another HR comment' AS 'Comment'
 ,CONVERT(DATE, '2021-01-01')  AS 'Date'
UNION ALL
SELECT
  54321                       AS 'ID'
 ,'Manager Comment'           AS 'Type'
 ,'This is a Manager comment' AS 'Comment'
 ,CONVERT(DATE, '2021-01-01') AS 'Date'
UNION ALL
SELECT
  54321                             AS 'ID'
 ,'Manager Comment'                 AS 'Type'
 ,'This is another Manager comment' AS 'Comment'
 ,CONVERT(DATE, '2020-01-01')       AS 'Date'
UNION ALL
SELECT
  54321                                    AS 'ID'
 ,'Manager Comment'                        AS 'Type'
 ,'This is another Manager comment aswell' AS 'Comment'
 ,CONVERT(DATE, '2019-01-01')              AS 'Date';



SELECT
  *
FROM (
  SELECT
    #COMMENTS.ID      AS 'ID'
   ,#COMMENTS.type + ' ' + CONVERT(NVARCHAR(20), ROW_NUMBER() OVER (PARTITION BY #COMMENTS.ID, #COMMENTS.type ORDER BY #COMMENTS.DATE ASC)) AS 'Comment Type'
   ,#COMMENTS.Comment AS 'Comment'

  FROM #COMMENTS
) AS SourceTable PIVOT (MAX([Comment]) FOR [Comment Type] IN ([Manager Comment 1], [Manager Comment 2], [Manager Comment 3], [Manager Comment 4], [Manager Comment 5],
[HR Comment 1], [HR Comment 2], [HR Comment 3], [HR Comment 4], [HR Comment 5])) AS PivotTable;



DROP TABLE #COMMENTS


Michael Z.
  • 1,453
  • 1
  • 15
  • 21
0

My other answer will only work if you know or want to limit the number of comment columns. With this answer I demonstrate how you would do this for any number of comments.

In order to do this you must create your column headers dynamically and execute you PIVOT query as a string using EXEC()

SELECT
  12345 AS 'ID'
 ,'Manager Comment' AS 'Type'
 ,'This is a Manager comment' AS 'Comment'
 ,CONVERT(DATE, '2021-01-01') AS 'Date' INTO Comments
UNION ALL
SELECT
  12345 AS 'ID'
 ,'HR Comment' AS 'Type'
 ,'This is a HR comment' AS 'Comment'
 ,CONVERT(DATE, '2020-01-01') AS 'Date'
UNION ALL
SELECT
  12345 AS 'ID'
 ,'HR Comment' AS 'Type'
 ,'This is another HR comment' AS 'Comment'
 ,CONVERT(DATE, '2021-01-01') AS 'Date'
UNION ALL
SELECT
  54321 AS 'ID'
 ,'Manager Comment' AS 'Type'
 ,'This is a Manager comment' AS 'Comment'
 ,CONVERT(DATE, '2021-01-01') AS 'Date'
UNION ALL
SELECT
  54321 AS 'ID'
 ,'Manager Comment' AS 'Type'
 ,'This is another Manager comment' AS 'Comment'
 ,CONVERT(DATE, '2020-01-01') AS 'Date'
UNION ALL
SELECT
  54321 AS 'ID'
 ,'Manager Comment' AS 'Type'
 ,'This is another Manager comment aswell' AS 'Comment'
 ,CONVERT(DATE, '2019-01-01') AS 'Date';

DECLARE @cols NVARCHAR(MAX) = '';

DECLARE @SQL NVARCHAR(MAX) = 'SELECT *
FROM (SELECT
    Comments.id AS ID
   ,Comments.type + SPACE(1) + CONVERT(NVARCHAR(20), ROW_NUMBER() OVER (PARTITION BY Comments.id, Comments.type ORDER BY Comments.DATE ASC)) AS CommentType
   ,Comments.Comment AS Comment

  FROM Comments) AS SourceTable PIVOT (MAX([Comment]) FOR [CommentType] IN (##COLUMNS##)) AS PivotTable;';


WITH COMMENTS1 AS
(
SELECT
Comments.id AS ID
 ,Comments.type + SPACE(1) + CONVERT(NVARCHAR(20), ROW_NUMBER() OVER (PARTITION BY Comments.id, Comments.type ORDER BY Comments.DATE ASC)) AS CommentType
 ,Comments.Comment AS Comment

FROM Comments
),
DISTINCT_COMMENTS AS
(
  SELECT DISTINCT CommentType
  FROM COMMENTS1
)
SELECT
@COLS = STRING_AGG('[' + DISTINCT_COMMENTS.CommentType + ']', ',')
FROM DISTINCT_COMMENTS;

SET @SQL = REPLACE(@SQL, '##COLUMNS##', @COLS);

EXEC(@SQL);
Michael Z.
  • 1,453
  • 1
  • 15
  • 21