T-SQL行到列:使用多列聚合进行透视

时间:2015-01-27 16:31:56

标签: sql sql-server tsql

例如我有下表:

CodInt          DocType         Qty (+)             Qty (-)             TotalCost (+)       TotalCost (-)
-----------------------------------------------------------------------------------------------------------
0208020015      2               NULL                -3.000000000        NULL                130.05000
0208020015      3               13056.000000000     79.000000000        547711.24000        3220.83000
0208020015      5               2.000000000         NULL                81.54000            NULL
0208020015      6               NULL                -11444.000000000    NULL                489120.75000

我需要将所有内容分组在一行中。所以最后我需要表格为CodInt + 24列,每个DocType有4列(总共有6个DocType)。

我知道我可以轻松地使用内部联接,但是我想知道是否有更简单/可理解的方法来实现它,因为内部联接往往有点大。我读到了一个PIVOT条款,但我不认为我可以在这种情况下使用它,或者没有完全理解它是如何工作的。

我正在寻找的例子(缩短,还会有16列):

CodInt          Qty1 (+)            Qty1 (-)        TotalCost1 (+)  TotalCost1 (-)  Qty2 (+)            Qty2 (-)            TotalCost2 (+)  TotalCost2 (-) .........
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
0208020015      NULL                NULL            NULL            NULL            NULL                -3.000000000        NULL            130.05000      .........

所以我的问题是:如何按CodInt对所有内容进行分组,将每个文档类型的列数相乘,并将列QtyTotalCost的信息放在新列上列?

1 个答案:

答案 0 :(得分:0)

您需要做的是UNPIVOT,然后PIVOT你的数据。请阅读此文档:Using PIVOT and UNPIVOT

评论版:使用多个聚合进行旋转

正如我从评论中看到的那样,构成这种情况的唯一问题是它需要PIVOT,聚合四个不同的列。要解决这个问题,只需要在最后一个支点之前再采取两个步骤:

  1. 取消汇总要聚合的列,以便它们从列移动到行:在这种情况下:[Qty (+)], [Qty (-)], [TotalCost (+)], [TotalCost (-)]
  2. 将未透视的列的名称与另一个旋转列(DocType)连接在一起,从而获得所有组合,如[Qty (+) 1], [Qty (+) 2], [Qty (+) 3]等。
  3. 您可以在this fiddle中查看它,并在此处获得完整的代码和说明:

    第一步:取消移动

    使用此查询,您可以将列[Qty (+)], [Qty (-)], [TotalCost (+)], [TotalCost (-)]移至不同的行,转到新的Name

    SELECT *
    FROM 
        (SELECT 
            CodInt, DocType, [Qty (+)], [Qty (-)], [TotalCost (+)], [TotalCost (-)] 
        FROM Test) Orig
    UNPIVOT
        ( Value FOR Name IN 
            ([Qty (+)], [Qty (-)], [TotalCost (+)], [TotalCost (-)])
        ) UnPiv
    

    你得到这样的东西:

    CodInt   DocType  Value  Name
    0208215  2         -3    Qty (-)
    0208215  2        130    TotalCost (-)
    

    第二步:获取最终聚合的名称

    它与以前的查询相同,但是,在选择列表中,而不是select *,连接NameDocType列,如下所示:

    SELECT 
        CodInt, 
        CAST(Name AS VARCHAR(20)) + ' ' + CAST(DocType AS VARCHAR(20)) Name,
        Value
    

    此时您会得到如下结果:

    CodInt   Name               Value
    0208215  Qty (-) 2          -3
    0208215  TotalCost (-) 2    130
    

    第三步,转动结果

    现在,您在其独立行中拥有所有所需的列,您只需将它们旋转即可。最终查询看起来像这样(使用CTE是为了可读性,是可选的):

    WITH Unpivoted AS (
        SELECT 
            CodInt, 
            CAST(Name AS VARCHAR(20)) + ' ' + CAST(DocType AS VARCHAR(20)) Name,
            Value
        FROM 
            ( SELECT 
                CodInt, DocType, [Qty (+)], [Qty (-)], [TotalCost (+)], [TotalCost (-)] 
            FROM Test ) UnPivSource
            UNPIVOT
            ( Value FOR Name IN 
                ([Qty (+)], [Qty (-)], [TotalCost (+)], [TotalCost (-)])
            ) UnPiv
    )
    SELECT * FROM
    ( SELECT CodInt, Name, Value FROM Unpivoted ) PivotSource
    PIVOT 
    (SUM(Value) FOR NAME IN
        (
        [Qty (+) 1], [Qty (+) 2], [Qty (+) 3], [Qty (+) 4], [Qty (+) 5], [Qty (+) 6], 
        [Qty (-) 1], [Qty (-) 2], [Qty (-) 3], [Qty (-) 4], [Qty (-) 5], [Qty (-) 6],
        [TotalCost (+) 1], [TotalCost (+) 2], [TotalCost (+) 3], 
        [TotalCost (+) 4], [TotalCost (+) 5], [TotalCost (+) 6], 
        [TotalCost (-) 1], [TotalCost (-) 2], [TotalCost (-) 3], 
        [TotalCost (-) 4], [TotalCost (-) 5], [TotalCost (-) 6]
        )
    ) Pivoted
    

    你得到最终结果,如下:

    CodInt   Qty (+) 1  Qty (+) 2  Qty (+) 3  Qty (+) 4  Qty (+) 5  Qty (+) 6  Qty (-) 1  Qty (-) 2  Qty (-) 3  Qty (-) 4  Qty (-) 5  Qty (-) 6  TotalCost (+) 1  TotalCost (+) 2  TotalCost (+) 3  TotalCost (+) 4  TotalCost (+) 5    TotalCost (+) 6  TotalCost (-) 1  TotalCost (-) 2  TotalCost (-) 3  TotalCost (-) 4  TotalCost (-) 5  TotalCost (-) 6
    0208215  NULL       NULL       13056      NULL       2          NULL       NULL       -3         79         NULL       NULL       -11444     NULL             NULL             547711           NULL             82                 NULL             NULL             130              3221             NULL             NULL             489121
    0208216  NULL       -8         127        NULL       NULL       928283     NULL       NULL       NULL       NULL       124        24         NULL             4567             2519             NULL             NULL               9292993          NULL             NULL             84               NULL             NULL             NULL