动态转动到固定数量的列

时间:2015-02-19 19:38:30

标签: sql sql-server tsql

这是我数据的结构

Name       TransID       Amount

Joe        123           56
Joe        124           55
Joe        125           58
Tom        126           31
Tom        127           48

我要求以下列格式报告此数据

Name      Amount1        Amount2

Joe       56             55
Joe       58
Tom       31             48

Joe在原始数据集中有三个Amount但我在视图中需要固定数量的列(两个)。因此,Joe的第三个Amount将作为新记录插入视图中。是否可以将其作为存储过程或创建视图来实现。

2 个答案:

答案 0 :(得分:4)

将问题分解为更小的步骤。这些是我要采取的步骤:

  • 使用ROW_NUMBER() OVER (PARTITION BY ...)

    Name       TransID       Amount    Row_Number
    
    Joe        123           56        1
    Joe        124           55        2
    Joe        125           58        3
    Tom        126           31        1 
    Tom        127           48        2
    
  • 减1。

    Name       TransID       Amount    RowNumberStartingWith0
    
    Joe        123           56        0
    Joe        124           55        1
    Joe        125           58        2
    Tom        126           31        0 
    Tom        127           48        1
    
  • 除以2,得到除法的结果,其余的模2:

    Name       TransID       Amount    Result  Remainder
    
    Joe        123           56        0       0
    Joe        124           55        0       1
    Joe        125           58        1       0
    Tom        126           31        0       0 
    Tom        127           48        0       1
    
  • 删除TransID列。余数总是0或1,所以你可以转向它:

    Name       Result  AmountForRemainder0 AmountForRemainder1
    
    Joe        0       56                  55
    Joe        1       58
    Tom        0       31                  48
    
  • 现在,您删除Result列并重命名列:

    Name      Amount1        Amount2
    
    Joe       56             55
    Joe       58
    Tom       31             48
    
  • 利润。

答案 1 :(得分:0)

尝试这个并告诉我。也请查看其他样本数据。我正在获得欲望输出。

DECLARE @t TABLE (
    NAME VARCHAR(50)
    ,TransID INT
    ,Amount INT
    )

INSERT INTO @t
VALUES ('Joe',123,56)
    ,('Joe',124,55)
    ,('Joe',125,58)
    ,('Tom',126,31)
    ,('Tom',127,48)
    ,('Tom',128,89)
    ,('Tom',129,90)
    ,('Joe',130,68);

WITH CTE
AS (
    SELECT *
        ,row_number() OVER (
            PARTITION BY NAME ORDER BY amount
            ) rn
    FROM @t
    )
    ,CTE1
AS (
    SELECT NAME
        ,(
            SELECT amount
            FROM cte
            WHERE rn = 1
                AND NAME = a.NAME
            ) [Amount1]
        ,(
            SELECT amount
            FROM cte
            WHERE rn = 2
                AND NAME = a.NAME
            ) [Amount2]
        ,rn
    FROM cte A
    WHERE rn = 1

    UNION ALL

    SELECT b.NAME
        ,a.amount
        ,isnull(c.amount, 0)
        ,a.rn
    FROM CTE1 B

    INNER JOIN CTE A ON a.NAME = b.NAME
        AND a.rn % 2 <> 0
        AND a.rn > 1
        AND b.rn <> a.rn
    OUTER APPLY (
        SELECT Amount
        FROM CTE C
        WHERE NAME = b.NAME
            AND rn % 2 = 0
            AND rn > 2
        ) c

    )
SELECT *
FROM cte1