SQL 服务器将行转置为新行 Table

SQL Server Transpose Rows Into New Table

我有一个 table,如下所示。我正在生成一个唯一 ID,另外两个引用其他 table 的 ID(ArgumentID 和 eventID),一个分类类型 (eQualType),然后是与 eventID 和 eQualType 关联的值。

实际上有 20 个不同的值列(在本示例中已缩短),其中绝大多数行仅包含值 1 中的内容。其他的将在 16-20 列中有一个数字(与给定事件关联的所有行和 eQualType 1-5 将填充相同数量的列)。

我正在尝试让下面的 table 转向...

UniqueID ArgumentIDs eventID eQualType Value1 Value2 Value3 Value4 
1              7       1         4       1      2      3      4 
2              10      1         7       23         
3              11      1         2       1      2      2      3
4              15      1         3       1      33     2      31
5              8       1         6       8          
6              3       1         1       105    106    107    108
7              9       1         5       0      0      0      0
8              12      2         4       1      2      3      4
9              16      2         1       91     92     93     94
10             19      2         2       1      2      2      3
11             17      2         5       0      0      0      0
12             4       2         3       12     3      2      4

在单独的 table 中插入类似下面的内容(理想情况下会插入到已经包含此格式数据的 table 中)。 ArgumentIDs 必须是占位符或空白,因为它不会引用另一个 table 中的任何内容,并且 eQualType 必须是一个与之前的任何值都不匹配的新值。

UniqueID ArgumentIDs eventID eQualType Value1 Value2 Value3 Value4 Value5
1            x          1       999      105     1      1      1      0
2            x          1       999      106     2      33     2      0
3            x          1       999      107     2      2      3      0
4            x          1       999      108     3      31     4      0
5            8          1       6        8

我不知道这是否可行,或者在加载到 SQL 之前进行转换是否更好。

我明白了。代码见下方。

INSERT INTO Results (eventID,Result1,Result2,Result3,Result4,Result5)
SELECT eventID, [1] as Result1, [2] as Result2, [3] as Result3, [4] as Result4, [5] as Result5
FROM
(SELECT [inputTable].eventID,[inputTable].eQualType,[inputTable].Value1
FROM eventQData
WHERE eQualType IN (1, 2, 3, 4, 5) AND (Value2 > 0)
) AS inputTable
PIVOT
(MAX(Value1)
FOR [eQualType] IN ([1],[2],[3],[4],[5])

当您将列 Value1, Value2, Value3, Value4 转置为行时:

Value1
Value2
Value3
Value4

您实际上在做的事情叫做 UNPIVOTing(不是旋转)。这在您的问题周围造成了一些混乱。但注意这有助于找到一个相当直接的解决方案。 (当然,事实证明你确实想将你的中间结果重新PIVOT到你的最终解决方案中。所以这仍然适用。)

下面的查询执行一个 UNPIVOT,用作 PIVOT 查询中的子查询。我发现很容易跟踪每个结果值来自的原始值列;您可以通过从最终结果中的 eQualType 中减去 100 来记录这一点。我的回答还演示了在最终输出中包含 Result6 列的效果。 (当然如果不需要也可以去掉。)

SELECT  eventID, 100 + ValueCol as eQualType,
        [1] as Result1, [2] as Result2, [3] as Result3, [4] as Result4, [5] as Result5, [6] as Result6
FROM (
        SELECT eventId, eQualType, CAST(RIGHT(ValueCol, 1) as int) as ValueCol, val
        FROM (  SELECT  eventId, eQualType, Value1, Value2, Value3, Value4
                FROM    @t1) src
        UNPIVOT (val FOR ValueCol IN (Value1, Value2, Value3, Value4)
                ) AS unpvt
    )as inp
PIVOT (MAX(val) FOR eQualType in ([1],[2],[3],[4],[5],[6])) pvt
ORDER BY 1,2

以下是使用您的示例输入数据的结果(根据您问题中的信息排除了 UniqueID 和 ArgumentID):

eventID     eQualType   Result1     Result2     Result3     Result4     Result5     Result6
----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
1           101         105         1           1           1           0           8
1           102         106         2           33          2           0           NULL
1           103         107         2           2           3           0           NULL
1           104         108         3           31          4           0           NULL
2           101         91          1           12          1           0           NULL
2           102         92          2           3           2           0           NULL
2           103         93          2           2           3           0           NULL
2           104         94          3           4           4           0           NULL

(8 row(s) affected)

请注意,除了您包含的无意义的第 5 行之外,我的结果与您的大部分示例输出相匹配。当然,我已经包含了 eventID=2 以及 Result6.

的结果