在不使用 MAX、AVG 等聚合函数的情况下,将行转置为 SQL 中的列

Transpose rows into columns in SQL without using aggregate functions like MAX, AVG etc

我有一个 table 这样的:

CREATE TABLE MyDataTable
(
     [RollNo] varchar(8), 
     [QuesBlock] int, 
     [RespVal] varchar(2)
);

INSERT INTO MyDataTable ([RollNo], [QuesBlock], [RespVal])
VALUES ('MBA0001', 1, A), ('MBA0001', 2, B), ('MBA0001', 3, D),
       ('MBA0002', 1, C), ('MBA0002', 2, A), ('MBA0002', 3, B),
       ('MBA0003', 1, B), ('MBA0003', 2, C), ('MBA0003', 3, A);

因此,我的源数据如下所示:

现在我想达到这样的目标 table 结构:

这基本上是在针对学校的基于 OMR 的测试中,将每个问题的候选人、问题答案制成表格。我在 QuesBlock 列中有固定数量的唯一值(只有 50),所以我可以接受硬编码。 我已经完成了 examples,其中 pivot 被用来实现类似的东西,但它们都使用了聚合函数,如 MAX、MIN、AVG 等来处理数值。但就我而言,RESPVAL 列的值都是文本的。我如何实现这一目标?

您可以将 max() 与 characters/string 一起使用。一个简单的旧样式 pivot 将适用于此:

select
    RollNo
  , Q1 = max(case when QuesBlock = 1 then RespVal else null end)
  , Q2 = max(case when QuesBlock = 2 then RespVal else null end)
  , Q3 = max(case when QuesBlock = 3 then RespVal else null end)
from MyDataTable
group by RollNo;

pivot() 像这样:

select
    RollNo
  , Q1
  , Q2
  , Q3
from (select RollNo, QuesBlock='Q'+convert(varchar(2),QuesBlock), RespVal
      from MyDataTable) as i
 pivot (max(RespVal) for QuesBlock in (Q1,Q2,Q3)) as p;

或动态 pivot() 像这样:

declare @query nvarchar(max);
declare @cols nvarchar(max);

select @cols = stuff((select ','+quotename('Q'+convert(varchar(2),QuesBlock))
         from MyDataTable as C
         group by c.QuesBlock
         order by c.QuesBlock
         for xml path('')), 1, 1, '');
set @query = 'select RollNo, '+@cols+'
      from(select RollNo, QuesBlock=''Q''+convert(varchar(2),QuesBlock), RespVal
        from MyDataTable) as i
      pivot
      (
        max(RespVal)
        for QuesBlock in ('+@cols+')
      ) p';
exec sp_executesql @query;

测试设置:http://rextester.com/TURW69000

全部三个return:

+---------+----+----+----+
| RollNo  | Q1 | Q2 | Q3 |
+---------+----+----+----+
| mba0001 | A  | B  | D  |
| mba0002 | C  | A  | B  |
| mba0003 | B  | C  | A  |
+---------+----+----+----+