简体   繁体   English

SQL - 多行到列 - Pivot? 交叉表?

[英]SQL - Multiple Rows to Columns - Pivot? Cross Table?

I have a table with the following results (from an SQL Query)我有一个包含以下结果的表(来自 SQL 查询)

ID ID Type类型 Comment评论
12345 12345 Manager Comment经理评论 This is a Manager comment这是经理评论
12345 12345 HR Comment人力资源评论 This is a HR comment这是HR评论
12345 12345 HR Comment人力资源评论 This is another HR comment这是另一个 HR 评论
54321 54321 Manager Comment经理评论 This is a Manager comment这是经理评论
54321 54321 Manager Comment经理评论 This is another Manager comment这是另一个经理评论
54321 54321 Manager Comment经理评论 This is another Manager comment aswell这也是经理的另一条评论

I'm tryring to get the output to look like this:我试图让 output 看起来像这样:

ID ID Manager Comment 1经理评论 1 Manager Comment 2经理评论 2 Manager Comment 3经理评论 3 HR Comment 1人力资源评论 1 HR Comment 2人力资源评论 2
12345 12345 This is a HR comment这是HR评论 This is a HR comment这是HR评论 This is another HR Comment这是另一个人力资源评论
54321 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.此评论数可以在 0 到 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.显然它不会容纳多条评论,我现在已经花了大约 3 个小时在这上面,所以任何帮助都将不胜感激。

Thanks Chris谢谢克里斯

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.我正在为每个评论文本添加一个行号,以便Manager Comment成为Manager Comment 1Manager Comment 2 ,具体取决于行号。

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然后,由于我们知道每种类型最多有五个评论,我们可以简单地在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


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()为此,您必须动态创建列标题并使用EXEC()PIVOT查询作为字符串执行

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM