Sql 基于给出空单元格的文本的服务器数据透视命令

Sql Server pivot command based on text giving null cells

我有一个table格式如下

╔════════╦══════════════╦════════╦════════════╦══════════╦════════╦══════════╦══════════╗
║ Answer ║ QuestionText ║ type   ║ QuestionID ║ ResultID ║ Action ║ Username ║ SurveyID ║
╠════════╬══════════════╬════════╬════════════╬══════════╬════════╬══════════╬══════════╣
║ FN 1   ║ First Name   ║ text   ║ 3467       ║ 2259     ║ 2259   ║ admin    ║ 308      ║
║ LN 1   ║ Last Name    ║ text   ║ 3468       ║ 2259     ║ 2259   ║ admin    ║ 308      ║
║ Male   ║ Gender       ║ radio  ║ 3466       ║ 2259     ║ 2259   ║ admin    ║ 308      ║
║ 12     ║ Age          ║ number ║ 3469       ║ 2259     ║ 2259   ║ admin    ║ 308      ║
║ FN 2   ║ First Name   ║ text   ║ 3467       ║ 2260     ║ 2260   ║ admin    ║ 308      ║
║ LN 2   ║ Last Name    ║ text   ║ 3468       ║ 2260     ║ 2260   ║ admin    ║ 308      ║
║ Female ║ Gender       ║ radio  ║ 3466       ║ 2260     ║ 2260   ║ admin    ║ 308      ║
║ 12     ║ Age          ║ number ║ 3469       ║ 2260     ║ 2260   ║ admin    ║ 308      ║
╚════════╩══════════════╩════════╩════════════╩══════════╩════════╩══════════╩══════════╝

我正在尝试使用以下数据透视查询对它进行数据透视。

SELECT [ResultID],[Username],[Action],[First Name],[Last Name],[Gender],[Age] from 
            (
                select * 
                from #myTab
           ) as y
            pivot 
            (
                 max(Answer)
                for QuestionText in ([First Name],[Last Name],[Gender],[Age])
            ) as p

但我得到以下 table 作为数据透视结果

╔══════════╦══════════╦════════╦════════════╦═══════════╦════════╦══════╗
║ ResultID ║ Username ║ Action ║ First Name ║ Last Name ║ Gender ║ Age  ║
╠══════════╬══════════╬════════╬════════════╬═══════════╬════════╬══════╣
║ 2259     ║ admin    ║ 2259   ║ NULL       ║ NULL      ║ NULL   ║ 12   ║
║ 2260     ║ admin    ║ 2260   ║ NULL       ║ NULL      ║ NULL   ║ 12   ║
║ 2259     ║ admin    ║ 2259   ║ NULL       ║ NULL      ║ Male   ║ NULL ║
║ 2260     ║ admin    ║ 2260   ║ NULL       ║ NULL      ║ Female ║ NULL ║
║ 2259     ║ admin    ║ 2259   ║ FN 1       ║ NULL      ║ NULL   ║ NULL ║
║ 2260     ║ admin    ║ 2260   ║ FN 2       ║ NULL      ║ NULL   ║ NULL ║
║ 2259     ║ admin    ║ 2259   ║ NULL       ║ LN 1      ║ NULL   ║ NULL ║
║ 2260     ║ admin    ║ 2260   ║ NULL       ║ LN 2      ║ NULL   ║ NULL ║
╚══════════╩══════════╩════════╩════════════╩═══════════╩════════╩══════╝

我不确定为什么会得到所有这些 NULL 值。如果有人能告诉我为什么会这样,以及获得以下数据透视输出的正确方法,那将是一个很大的帮助:

╔══════════╦══════════╦════════╦════════════╦═══════════╦════════╦══════╗
║ ResultID ║ Username ║ Action ║ First Name ║ Last Name ║ Gender ║ Age  ║
╠══════════╬══════════╬════════╬════════════╬═══════════╬════════╬══════╣
║ 2259     ║ admin    ║ 2259   ║ FN 1       ║ LN 1      ║ Male   ║ 12   ║
║ 2260     ║ admin    ║ 2260   ║ FN 2       ║ LN 2      ║ Female ║ 12   ║
╚══════════╩══════════╩════════╩════════════╩═══════════╩════════╩══════╝

Source table in csv format

这是预期的行为...您应该使用带有聚合函数的 GROUP BY(如 Max() 或 First() 或字符串连接(可能是东西?),具体取决于您的要求)以将结果减少到每个实体单行(由您分组的键定义)

编辑:尝试;

SELECT 
[ResultID],
max([Username]) as Username,
max([Action]) as action,
max([First Name]) as FirstName,
max([Last Name]) as LastName,
max([Gender]) as gender,
max([Age]) as age from 
            (
                select * 
                from #myTab
           ) as y
            pivot 
            (
                 max(Answer)
                for QuestionText in ([First Name],[Last Name],[Gender],[Age])
            ) as p
GROUP BY 
    ResultId

只限制X-Axis、Y-Axis(n)和Value所需的字段

Select [ResultID],[Username],[Action],[First Name],[Last Name],[Gender],[Age] 
 From (
        Select resultid
              ,Action 
              ,Username
              ,questiontext
              ,answer
        From  #Table21
    ) y
   pivot (max(Answer) for QuestionText in ([First Name],[Last Name],[Gender],[Age])) P 
CREATE TABLE #Table21
    ([Answer] varchar(6), [QuestionText] varchar(10), [type] varchar(6), [QuestionID] int, [ResultID] int, [Action] int, [Username] varchar(5), [SurveyID] int)
;

INSERT INTO #Table21
    ([Answer], [QuestionText], [type], [QuestionID], [ResultID], [Action], [Username], [SurveyID])
VALUES
    ('FN 1', 'First Name', 'text', 3467, 2259, 2259, 'admin', 308),
    ('LN 1', 'Last Name', 'text', 3468, 2259, 2259, 'admin', 308),
    ('Male', 'Gender', 'radio', 3466, 2259, 2259, 'admin', 308),
    ('12', 'Age', 'number', 3469, 2259, 2259, 'admin', 308),
    ('FN 2', 'First Name', 'text', 3467, 2260, 2260, 'admin', 308),
    ('LN 2', 'Last Name', 'text', 3468, 2260, 2260, 'admin', 308),
    ('Female', 'Gender', 'radio', 3466, 2260, 2260, 'admin', 308),
    ('12', 'Age', 'number', 3469, 2260, 2260, 'admin', 308)

with cte as
(
SELECT [ResultID],[Username],[Action],[First Name],[Last Name],[Gender],[Age] from 
            (
                select * 
                from #Table21
           ) as y
            pivot 
            (
                 max(Answer)
                for QuestionText in ([First Name],[Last Name],[Gender],[Age])
            ) as p
            )


SELECT   
     [ResultID],  
     max([Username]) AS [Username],  
     MAX([Action]) AS [Action],  
     MAX([First Name]) AS [First Name],  
     MAX([Last Name]) AS [Last Name]  ,
     MAX([Gender]) AS [Gender],
     MAX([Age]) AS [Age]
FROM CTE  
GROUP BY [ResultID];  

输出

ResultID    Username    Action  First Name  Last Name   Gender  Age
2259    admin   2259    FN 1    LN 1    Male    12
2260    admin   2260    FN 2    LN 2    Female  12

您还可以将 CASE 表达式与聚合一起使用,以基本上对结果进行透视。我经常使用它,因为如果出于某种原因我想添加另一个聚合列,我可以不必执行另一个 PIVOT。在某些情况下它也更快。

SELECT 
    [ResultID],
    [UserName],
    [Action],
    MAX(CASE WHEN c.[QuestionText] = 'First Name' THEN [Answer] END) as [First Name],
    MAX(CASE WHEN c.[QuestionText] = 'Last Name' THEN [Answer] END) as [Last Name],
    MAX(CASE WHEN c.[QuestionText] = 'Gender' THEN [Answer] END) as [Gender],
    MAX(CASE WHEN c.[QuestionText] = 'Age' THEN [Answer] END) as [Age]
FROM 
    cte c
GROUP BY
    [ResultID],
    [UserName],
    [Action]

示例:

WITH cte AS (SELECT * FROM (
VALUES
    ('FN 1', 'First Name', 'text', 3467, 2259, 2259, 'admin', 308),
    ('LN 1', 'Last Name', 'text', 3468, 2259, 2259, 'admin', 308),
    ('Male', 'Gender', 'radio', 3466, 2259, 2259, 'admin', 308),
    ('12', 'Age', 'number', 3469, 2259, 2259, 'admin', 308),
    ('FN 2', 'First Name', 'text', 3467, 2260, 2260, 'admin', 308),
    ('LN 2', 'Last Name', 'text', 3468, 2260, 2260, 'admin', 308),
    ('Female', 'Gender', 'radio', 3466, 2260, 2260, 'admin', 308),
    ('12', 'Age', 'number', 3469, 2260, 2260, 'admin', 308)
) t([Answer],[QuestionText],[type],[QuestionID],[ResultID],[Action],[Username],[SurveyID]))

SELECT 
    [ResultID],
    [UserName],
    [Action],
    MAX(CASE WHEN c.[QuestionText] = 'First Name' THEN [Answer] END) as [First Name],
    MAX(CASE WHEN c.[QuestionText] = 'Last Name' THEN [Answer] END) as [Last Name],
    MAX(CASE WHEN c.[QuestionText] = 'Gender' THEN [Answer] END) as [Gender],
    MAX(CASE WHEN c.[QuestionText] = 'Age' THEN [Answer] END) as [Age]
FROM 
    cte c
GROUP BY
    [ResultID],
    [UserName],
    [Action]


ResultID    UserName Action      First Name Last Name Gender Age
----------- -------- ----------- ---------- --------- ------ ------
2259        admin    2259        FN 1       LN 1      Male   12
2260        admin    2260        FN 2       LN 2      Female 12