PIVOT是连接和转换行的正确方法吗?

时间:2018-01-31 12:12:33

标签: sql-server

在MS SQL Server 2016中

select 
    mdl_user.firstname + ' ' + mdl_user.lastname as studentname
    , mdl_quiz.name as quizname
    , mdl_quiz_attempts.attempt as attemptnumber
    , mdl_quiz_attempts.timefinish as attemptdate
    , mdl_quiz_attempts.sumgrades as attemptgrade
from mdl_quiz_attempts 
join mdl_quiz on mdl_quiz.id = mdl_quiz_attempts.quiz
join mdl_user on mdl_user.id = mdl_quiz_attempts.userid
order by mdl_user.id, mdl_quiz.name, mdl_quiz_attempts.attempt;

给我以下输出:

studentname   quizname                    attemptnumber   attemptdate         attemptgrade
Mariy Vickery Income Tax Assessment       1               2017/03/30 06:50    26
Jan Le Roux   Fundamentals Assessment     1               2017/02/28 08:15    36
Jan Le Roux   Income Tax Assessment       1               2017/03/30 07:34    32
Andrew Small  Fundamentals Assessment     1               2017/02/28 10:34    30
Andrew Small  Income Tax Assessment       1               2017/03/30 11:24    27
Andrew Small  Income Tax Assessment       2               2017/03/30 12:15    32
Deon Lenark   Fundamentals Assessment     1               2017/02/28 10:22    29
Deon Lenark   Income Tax Assessment       1               2017/03/30 11:05    35
Chris Du Bill Fundamentals Assessment     1               2017/02/28 10:25    34
Chris Du Bill Income Tax Assessment       1               2017/03/30 08:06    34
Craig Eben    Fundamentals Assessment     1               2017/02/28 12:43    35
Craig Eben    Income Tax Assessment       1               2017/03/30 11:36    28
Craig Eben    Income Tax Assessment       2               2017/03/30 12:05    28
Charm Grey    Fundamentals Assessment     1               2017/02/28 08:33    34
Charm Grey    Income Tax Assessment       1               2017/03/30 12:33    35
Jaco Cloete   Income Tax Assessment       1               2017/03/30 09:04    32
Dirk Schaan   Fundamentals Assessment     1               2017/02/28 08:04    34
Dirk Schaan   Income Tax Assessment       1               2017/03/30 09:03    11
Dirk Schaan   Income Tax Assessment       2               2017/03/30 11:37    30
Deon Grobler  Income Tax Assessment       1               2017/03/30 07:49    27
Deon Grobler  Income Tax Assessment       2               2017/03/31 12:45    31
Ester Shannah Fundamentals Assessment     1               2017/02/28 10:32    36
Ester Shannah Income Tax Assessment       1               2017/03/30 11:32    30
Ester Shannah Income Tax Assessment       2               2017/03/30 12:21    35
Eve Haywood   Fundamentals Assessment     1               2017/02/28 07:36    33
Eve Haywood   Income Tax Assessment       1               2017/03/30 07:28    32
Fred Bezzo    Income Tax Assessment       1               2017/03/30 08:22    30
Fred Bezzo    Income Tax Assessment       2               2017/03/31 11:54    31

每个学生名已完成两个测验中的一个或两个(测验名称)。有些学生尝试过一次或两次测验(如trynumber栏所示)。

我想“转动”数据,以便每个学生的所有结果都显示在一行中,如下所示:

=================================================================
studentname     Fundamentals Assessment     Income Tax Assessment
=================================================================
Mariy Vickery                               2017/03/30 06:50 - 26
-----------------------------------------------------------------
Jan Le Roux     2017/02/28 08:15 - 36       2017/03/30 07:34 - 32
-----------------------------------------------------------------
Andrew Small    2017/02/28 10:34 - 30       2017/03/30 11:24 - 27
                2017/03/30 12:15 - 32
-----------------------------------------------------------------
Deon Lenark     2017/02/28 10:22 - 29       2017/03/30 11:05 - 35
-----------------------------------------------------------------
Chris Du Bill   2017/02/28 10:25 - 34       2017/03/30 08:06 - 34
-----------------------------------------------------------------
Craig Eben      2017/02/28 12:43 - 35       2017/03/30 11:36 - 28
                                            2017/03/30 12:05 - 58
-----------------------------------------------------------------
Charm Grey      2017/02/28 08:33 - 34       2017/03/30 12:33 - 35
-----------------------------------------------------------------
Jaco Cloete     2017/03/30 09:04 - 32
-----------------------------------------------------------------
Dirk Schaan     2017/02/28 08:04 - 34       2017/03/30 09:03 - 11
                                            2017/03/30 11:37 - 30
-----------------------------------------------------------------
Deon Grobler                                2017/03/30 07:49 - 27
                                            2017/03/31 12:45 - 31
-----------------------------------------------------------------
Ester Shannah   2017/02/28 10:32 - 22       2017/03/30 11:32 - 30
                2017/02/28 15:20 - 36       2017/03/30 12:21 - 35
-----------------------------------------------------------------
Eve Haywood     2017/02/28 07:36 - 33       2017/03/30 07:28 - 32
-----------------------------------------------------------------
Fred Bezhout                                2017/03/30 08:22 - 30
                                            2017/03/31 11:54 - 31
-----------------------------------------------------------------

但是PIVOT()函数执行聚合,我不想这样做 - 我希望包含每个学生名的所有成绩/尝试。

以下PIVOT()不返回我想要的内容 - 它只返回一个尝试次数(因为max(quiz_grade)  聚合)当有多次尝试时。并且它在每一行重复学生名称,看起来很难看:

select 
    * 
from (
    select 
        mdl_user.firstname + ' ' + mdl_user.lastname as fullname,
        mdl_quiz.name as quiz_name,  
        mdl_quiz_grades.grade as quiz_grade
    from mdl_quiz
    join mdl_quiz_grades on mdl_quiz.id = mdl_quiz_grades.quiz
    join mdl_course on mdl_course.id = mdl_quiz.course
    join mdl_user on mdl_user.id = mdl_quiz_grades.userid
) source
pivot ( 
    max(quiz_grade)
    for quiz_name in (
        [Fundamentals Assessment],
        [Income Tax Assessment]
    )
) as PIVT
order by fullname

所以它看起来像PIVOT()这里使用的函数不正确?如何“转动”数据并连接trytdate和attemptgrade列,如上面的示例所示?

3 个答案:

答案 0 :(得分:2)

你可以尝试这样的东西和xml路径:

DECLARE @myTable TABLE(studentname VARCHAR(20),
      quizname VARCHAR(50),
      attemptnumber INT,
      attemptdate DATETIME,
      attemptgrade INT);


INSERT INTO @myTable VALUES
    ('Mariy Vickery', 'Income Tax Assessment', 1, '2017/03/30 06:50', 26)
    , ('Jan Le Roux', 'Fundamentals Assessment', 1, '2017/02/28 08:15', 36) 
    , ('Jan Le Roux', 'Income Tax Assessment', 1, '2017/03/30 07:34', 32) 
    , ('Andrew Small', 'Fundamentals Assessment', 1, '2017/02/28 10:34', 30) 
    , ('Andrew Small', 'Income Tax Assessment', 1, '2017/03/30 11:24', 27)
    , ('Andrew Small', 'Income Tax Assessment', 2, '2017/03/30 12:15', 32);

SELECT * 
FROM 
(
    SELECT 
        studentname as fullname,
        quizname as quiz_name,  
        STUFF( (SELECT + '  ' + CAST(attemptdate AS VARCHAR(50)) + ' - ' 
                    + CAST(attemptgrade AS VARCHAR(3)) AS quiz_grade
                FROM @myTable si 
                WHERE si.studentname = so.studentname and si.quizname = so.quizname
                FOR XML PATH(''), TYPE).value('.', 'varchar(max)'),1,1,''
        ) AS quiz_grade
    FROM @myTable so 
) SOURCE
PIVOT 
( 
    MAX(quiz_grade)
    FOR quiz_name IN ([Fundamentals Assessment],[Income Tax Assessment])
) AS PIVT
ORDER BY fullname

答案 1 :(得分:1)

试试这个 -

DECLARE @myTable TABLE(studentname VARCHAR(20),
      quizname VARCHAR(50),
      attemptnumber INT,
      attemptdate DATETIME,
      attemptgrade INT);
DECLARE @myTable1 TABLE(studentname VARCHAR(20),
      [Fundamentals Assessment] VARCHAR(MAX),
      [Income Tax Assessment] VARCHAR(MAX));

INSERT INTO @myTable VALUES
    ('Mariy Vickery', 'Income Tax Assessment', 1, '2017/03/30 06:50', 26)
    , ('Jan Le Roux', 'Fundamentals Assessment', 1, '2017/02/28 08:15', 36) 
    , ('Jan Le Roux', 'Income Tax Assessment', 1, '2017/03/30 07:34', 32) 
    , ('Andrew Small', 'Fundamentals Assessment', 1, '2017/02/28 10:34', 30) 
    , ('Andrew Small', 'Income Tax Assessment', 1, '2017/03/30 11:24', 27)
    , ('Andrew Small', 'Income Tax Assessment', 2, '2017/03/30 12:15', 32)
    , ('Deon Lenark', 'Fundamentals Assessment', 1, '2017/02/28 10:22', 35)
    , ('Deon Lenark', 'Income Tax Assessment', 1, '2017/03/30 11:05', 34);


INSERT INTO @myTable1
SELECT studentname, 
    MAX([Fundamentals Assessment]) [Fundamentals Assessment], 
    MAX([Income Tax Assessment]) [Income Tax Assessment]
FROM
(
    SELECT studentname, IIF([Fundamentals Assessment] IS NOT NULL, 
        CONCAT([Fundamentals Assessment],' - ' ,attemptgrade),NULL) 
            AS [Fundamentals Assessment],
        IIF([Income Tax Assessment] IS NOT NULL, 
        CONCAT([Income Tax Assessment],' - ' ,attemptgrade),NULL) 
            AS [Income Tax Assessment], attemptnumber
    FROM
    (
        SELECT studentname, 
         IIF(quizname = 'Fundamentals Assessment',attemptdate,NULL) 
                AS [Fundamentals Assessment]
            ,IIF(quizname = 'Income Tax Assessment',attemptdate,NULL) 
                AS [Income Tax Assessment]
            ,attemptgrade, attemptnumber
        FROM @myTable
    ) AS A
)B
GROUP BY studentname, attemptnumber
ORDER BY studentname, attemptnumber


SELECT DISTINCT studentname, E.[Fundamentals Assessment], D.[Income Tax Assessment] 
    FROM @myTable1 p1
   CROSS APPLY ( 
        SELECT [Income Tax Assessment] + '  ' 
        FROM @myTable1 p2
        WHERE p2.studentname = p1.studentname 
        ORDER BY [Income Tax Assessment] 
        FOR XML PATH('') 
    )  D ( [Income Tax Assessment] )
    CROSS APPLY ( 
        SELECT [Fundamentals Assessment] + '  '
        FROM @myTable1 p2
        WHERE p2.studentname = p1.studentname 
        ORDER BY [Fundamentals Assessment] 
        FOR XML PATH('') 
    )  E ( [Fundamentals Assessment] )

答案 2 :(得分:1)

如果您需要动态版

示例

Declare @SQL varchar(max) = '
Select *
 From (
        Select Distinct
               studentname 
              ,Item = quizname
              ,value = replace( Stuff((Select concat(format(attemptdate,''|yyyy/MM/dd HH:mm - ''),attemptgrade) From YourTable Where studentname=A.studentname and quizname=A.quizname For XML Path ('''')),1,1,'''') ,''|'',char(13))
         From  YourTable A
      ) A
 Pivot (max([Value]) For [Item] in (' + Stuff((Select Distinct ','+QuoteName(quizname) 
                                               From YourTable  
                                               For XML Path('')),1,1,'')  + ') ) p'
--Print @SQL
Exec(@SQL);

<强>返回

studentname     Fundamentals Assessment Income Tax Assessment
Andrew Small    2017/02/28 10:34 - 30   2017/03/30 11:24 - 27
                                        2017/03/30 12:15 - 32
Charm Grey      2017/02/28 08:33 - 34   2017/03/30 12:33 - 35
Chris Du Bill   2017/02/28 10:25 - 34   2017/03/30 08:06 - 34
Craig Eben      2017/02/28 12:43 - 35   2017/03/30 11:36 - 28
                                        2017/03/30 12:05 - 28
Deon Grobler    NULL                    2017/03/30 07:49 - 27
                                        2017/03/31 12:45 - 31
Deon Lenark     2017/02/28 10:22 - 29   2017/03/30 11:05 - 35
Dirk Schaan     2017/02/28 08:04 - 34   2017/03/30 09:03 - 11
                                        2017/03/30 11:37 - 30
Ester Shannah   2017/02/28 10:32 - 36   2017/03/30 11:32 - 30
                                        2017/03/30 12:21 - 35
Eve Haywood     2017/02/28 07:36 - 33   2017/03/30 07:28 - 32
Fred Bezzo      NULL                    2017/03/30 08:22 - 30
                                        2017/03/31 11:54 - 31
Jaco Cloete     NULL                    2017/03/30 09:04 - 32
Jan Le Roux     2017/02/28 08:15 - 36   2017/03/30 07:34 - 32
Mariy Vickery   NULL                    2017/03/30 06:50 - 26