繁体   English   中英

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

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

我有一个包含以下结果的表(来自 SQL 查询)

ID 类型 评论
12345 经理评论 这是经理评论
12345 人力资源评论 这是HR评论
12345 人力资源评论 这是另一个 HR 评论
54321 经理评论 这是经理评论
54321 经理评论 这是另一个经理评论
54321 经理评论 这也是经理的另一条评论

我试图让 output 看起来像这样:

ID 经理评论 1 经理评论 2 经理评论 3 人力资源评论 1 人力资源评论 2
12345 这是HR评论 这是HR评论 这是另一个人力资源评论
54321 这是经理评论 这是另一个经理评论 这也是经理的另一条评论

此评论数可以在 0 到 5 之间变化。

我尝试了以下方法,但它仅适用于每个部分的最新评论:

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;

显然它不会容纳多条评论,我现在已经花了大约 3 个小时在这上面,所以任何帮助都将不胜感激。

谢谢克里斯

请参阅最后的工作示例。 在示例中,我给评论一个日期,以便可以对它们进行相应的排序。

我在做什么:

我正在为每个评论文本添加一个行号,以便Manager Comment成为Manager Comment 1Manager Comment 2 ,具体取决于行号。

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

工作示例:

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


我的其他答案只有在您知道或想要限制评论栏的数量时才有效。 通过这个答案,我将演示如何针对任意数量的评论执行此操作。

为此,您必须动态创建列标题并使用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