首页 > 解决方案 > 在 SQL Server 中将行转入具有固定行但内容未知的列

问题描述

我已经看到了很多与将行旋转为列相关的问题,但没有任何与我的问题相似的问题能够取得任何进展。

我有一个看起来像这样的数据集:

| candidate | qualification | unit | passed |
---------------------------------------------
| C1        | Q1            | U1-1 | 1      |
| C1        | Q1            | U1-2 | 1      |
| C1        | Q2            | U2-1 | 0      |
| C1        | Q2            | U2-2 | 1      |
| C2        | Q1            | U1-1 | 0      |
| C2        | Q1            | U1-2 | 0      |
| C2        | Q2            | U2-1 | 1      |
| C2        | Q2            | U2-2 | 1      |

每个候选人都可以注册多个资格,每个资格都有多个可以通过(1)或失败(0)的单元。

我需要将数据转换为如下所示:

| candidate | qualification | unit_1 | unit_1_passed | unit_2 | unit_2_passed |
-------------------------------------------------------------------------------
| C1        | Q1            | U1-1   | 1             | U1-2   | 1             |
| C1        | Q2            | U2-1   | 0             | U2-2   | 1             |
| C2        | Q1            | U1-1   | 0             | U1-2   | 0             |
| C2        | Q2            | U2-1   | 1             | U2-2   | 1             |

这样每个资格和是否通过的单元都会旋转到一列中。

我知道每个资格总会有固定数量的单位,但我不知道单位名称是什么

我的查询目前看起来像:

select
  candidate,
  qualification,
  unit,
  passed
from exams

但我不知道如何将行旋转成列。

提前致谢。

标签: sqlsql-serverpivot

解决方案


您可以使用窗口函数 row_number() 为每个候选人/资格组中的每个单元分配一个排名,然后使用条件聚合进行旋转:

select
    candidate,
    qualification,
    max(case when rn = 1 then unit end) unit_1,
    max(case when rn = 1 then passed end) unit_1_passed,
    max(case when rn = 2 then unit end) unit_2,
    max(case when rn = 2 then passed end) unit_2_passed
from (
    select
        t.*,
        row_number() over(
            partition by candidate, qualification 
            order by unit
        ) rn
    from exams t
) t
group by candidate, qualification 

推荐阅读