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
您实际上在做的事情叫做 UNPIVOT
ing(不是旋转)。这在您的问题周围造成了一些混乱。但注意这有助于找到一个相当直接的解决方案。 (当然,事实证明你确实想将你的中间结果重新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
.
的结果
我有一个 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
您实际上在做的事情叫做 UNPIVOT
ing(不是旋转)。这在您的问题周围造成了一些混乱。但注意这有助于找到一个相当直接的解决方案。 (当然,事实证明你确实想将你的中间结果重新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
.