【问题标题】:SQL Server Transpose Rows Into New TableSQL Server 将行转置到新表中
【发布时间】:2016-12-29 02:52:50
【问题描述】:

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

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

我正在尝试让下表旋转...

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

在一个单独的表中插入类似下面的内容(理想情况下会插入到该表中,该表已经包含这种格式的数据)。 ArgumentID 必须是占位符或空白,因为它不会引用另一个表中的任何内容,并且 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 之前进行转换。

【问题讨论】:

  • “让表格旋转”到底是什么意思?您如何根据基表中包含的值计算结果中的Value 列?它看起来像聚合值列并将它们作为新列添加到结果表中......
  • 结果表中的 Value1 列是基表的第 6 行,Value2 是第 3 行,以此类推
  • 基本上,基表中的行被转置为结果表中的列,由 eventID 聚集在一起
  • 好的,您想将输入的值列转置为不同的结果行(每个值列一行),并为每行添加另一个具有相同 eventID 的结果“值”列。我认为您应该更新您的问题并重命名结果表 e 的值列名称。 G。进入“Row1Value”、“Row2Value”等并完成示例结果,解释输入行#2和#5的处理逻辑(#2没有出现,#5的处理令人惊讶)。我认为你可以通过两个或三个 pivot/unpivot 函数和正确的过滤器来实现你的目标......
  • @RYoda 听起来 OP 实际上想要 UNPIVOT,而不是枢轴。

标签: sql sql-server pivot


【解决方案1】:

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

价值1 价值2 价值3 价值4

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

下面的查询执行一个 UNPIVOT,它用作 PIVOT 查询中的子查询。我发现跟踪每个 Result 值来自的原始 Value 列很容易;您可以通过在最终结果中从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 结果1 结果2 结果3 结果4 结果5 结果6 ----------- ------------ ----------- ----------- ------ ----- ----------- ----------- ----------- 1 101 105 1 1 1 0 8 1 102 106 2 33 2 0 空 1 103 107 2 2 3 0 空 1 104 108 3 31 4 0 空 2 101 91 1 12 1 0 空 2 102 92 2 3 2 0 空 2 103 93 2 2 3 0 空 2 104 94 3 4 4 0 空 (受影响的 8 行)

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

【讨论】:

    【解决方案2】:

    我想通了。代码见下文。

    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])
    

    【讨论】:

    • 我可以理解 OP 接受他/她自己的答案,因为鉴于问题中的样本输入/输出数据不完整,只有一个人可以实际测试这一点。但为什么要投赞成票?这不能回答问题。它适用未说明的规则。它在语法上是不正确的。即使在修复了错误之后,它也远不能产生预期的输出。
    • 嗯,在赏金截止日期结束之前用开放的赏金回答自己的问题,而不回答问题的所有部分似乎确实有点不合时宜。我认为 Craig 的答案更接近所质疑的内容,并且应该通过接受它来获得荣誉(特别是如果你看看他花费了多少时间来寻找不平凡的答案)。
    猜你喜欢
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多