2014-09-02 19 views
0

我试图摆动这个SQL Server表,但是我正在努力将我的头围绕在我需要做的事情上。我可以做一个基本的支点,但是这变得非常具有挑战性。我在本质上有再次转换下表SQL Server:数据透视表和转发器

Company Code Account Class   Period Billings Collections Debtors 
-------------------------------------------------------------------------------- 
500    Accounts Receiveable 1  xx   xx   xx 
500    Accounts Receiveable 2  xxx   xx   xx 
500    Accounts Receiveable 3  xx   xx   xxx 
500    Accounts Receiveable 1  xx   xx   xx 

Company Code  Account Class        1 2 3 
-------------------------------------------------------------------------- 
500    Accounts Receiveable  Billings  xx xx xx 
500    Accounts Receiveable  Collections xxx xx xx 
500    Accounts Receiveable  Debtors  xx xx xxx 

我正打算到一个支点和上一列,然后加入表本身,进行另一支点本身,但我不捕获列名称。任何建议将不胜感激。

+1

@Bluefeet:PIVOT的问题! :-) – 2014-09-02 16:52:09

+3

@marc_s你响了? :) – Taryn 2014-09-02 17:17:01

回答

7

你的想法是正确的,你需要首先unpivot才能得到你想要的最终结果。您需要将Billings,CollectionsDebtors的多个列转换为多个行,然后将Period值转换为列。

你没有指定你使用的是什么版本的SQL Server,但是在SQL Server 2005开始,您可以使用CROSS APPLY到UNPIVOT:

select 
    CompanyCode, 
    AccountClass, 
    period, 
    [Type], 
    Value 
from yourtable t 
cross apply 
(
    select 'Billings', Billings union all 
    select 'Collections', Collections union all 
    select 'Debtors', Debtors 
) c ([Type], value); 

Demo。这将您的数据转换成格式:

| COMPANYCODE |   ACCOUNTCLASS | PERIOD |  TYPE | VALUE | 
|-------------|----------------------|--------|-------------|-------| 
|   500 | Accounts Receiveable |  1 | Billings | xx | 
|   500 | Accounts Receiveable |  1 | Collections | xx | 
|   500 | Accounts Receiveable |  1 |  Debtors | xx | 
|   500 | Accounts Receiveable |  2 | Billings | xxx | 
|   500 | Accounts Receiveable |  2 | Collections | xx | 

你会发现,你现在必须为每个BillingsCollectionsDebtors一行。现在,您可以将旋转功能的Period列:

select 
    CompanyCode, 
    AccountClass, 
    Type, 
    [1], 
    [2], 
    [3] 
from 
(
    select 
    CompanyCode, 
    AccountClass, 
    period, 
    [Type], 
    Value 
    from yourtable t 
    cross apply 
    (
    select 'Billings', Billings union all 
    select 'Collections', Collections union all 
    select 'Debtors', Debtors 
) c ([Type], value) 
) unp 
pivot 
(
    max(value) 
    for period in ([1], [2], [3]) 
) piv; 

SQL Fiddle with Demo。这给你一个结果:

| COMPANYCODE |   ACCOUNTCLASS |  TYPE | 1 | 2 | 3 | 
|-------------|----------------------|-------------|----|-----|-----| 
|   500 | Accounts Receiveable | Billings | xx | xxx | xx | 
|   500 | Accounts Receiveable | Collections | xx | xx | xx | 
|   500 | Accounts Receiveable |  Debtors | xx | xx | xxx | 

现在,如果你有在CompanyCodeAccountClass可能出现多次为同一Period的可能性,你需要创建一个可以用来返回多个不同的值行。在这种情况下,您需要使用类似于row_number()的窗口函数来为这些组合创建唯一序列。我会稍微修改上面的代码:

select 
    CompanyCode, 
    AccountClass, 
    Type, 
    [1], 
    [2], 
    [3] 
from 
(
    select 
    CompanyCode, 
    AccountClass, 
    seq, 
    period, 
    [Type], 
    Value 
    from 
    (
    select CompanyCode, AccountClass, Period, Billings, 
     Collections, Debtors, 
     seq = row_number() over(partition by CompanyCode, AccountClass, Period 
           order by CompanyCode, AccountClass) 
    from yourtable 
) t 
    cross apply 
    (
    select 'Billings', Billings union all 
    select 'Collections', Collections union all 
    select 'Debtors', Debtors 
) c ([Type], value) 
) unp 
pivot 
(
    max(value) 
    for period in ([1], [2], [3]) 
) piv; 

请参阅SQL Fiddle with Demo。您会注意到这会将结果略微更改为:

| COMPANYCODE |   ACCOUNTCLASS |  TYPE | 1 |  2 |  3 | 
|-------------|----------------------|-------------|----|--------|--------| 
|   500 | Accounts Receiveable | Billings | xx | xxx |  xx | 
|   500 | Accounts Receiveable | Collections | xx |  xx |  xx | 
|   500 | Accounts Receiveable |  Debtors | xx |  xx | xxx | 
|   500 | Accounts Receiveable | Billings | xx | (null) | (null) | 
|   500 | Accounts Receiveable | Collections | xx | (null) | (null) | 
|   500 | Accounts Receiveable |  Debtors | xx | (null) | (null) | 
+0

看到 - 你确实知道答案! :-) – 2014-09-02 17:18:52

+0

哇,这是非常全面的。不幸的是,当我尝试应用你的方法时,我收到错误。我将不得不深入研究这一点。 – Calgar99 2014-09-02 17:32:24

+0

@ Calgar99你的错误是什么?你使用的是什么版本的SQL Server? – Taryn 2014-09-02 17:35:12

1

请尝试以下操作。首先您需要UNPIVOT Billings,CollectionsDebtors然后是PIVOT Period

declare @table table 
    ([CompanyCode] int, [AccountClass] varchar(20), [Period] int, [Billings] varchar(3), [Collections] varchar(3), [Debtors] varchar(3)); 

INSERT INTO @table 
    ([CompanyCode], [AccountClass], [Period], [Billings], [Collections], [Debtors]) 
VALUES 
    (500, 'Accounts Receiveable', 1, 'xx', 'xx', 'xx'), 
    (500, 'Accounts Receiveable', 2, 'xxx', 'xx', 'xx'), 
    (500, 'Accounts Receiveable', 3, 'xx', 'xx', 'xxx'), 
    (500, 'Accounts Receiveable', 1, 'xx', 'xx', 'xx'); 

SELECT * 
    FROM (
     SELECT [CompanyCode], [AccountClass], [Period], [Type], [Value] 
     FROM @table 
     UNPIVOT ([Value] FOR [Type] IN ([Billings],[Collections],[Debtors])) AS u 
     ) as t 
    PIVOT (MAX(Value) FOR [Period] IN ([1], [2], [3])) AS pvt; 
    -- use SUM(Value) if Billings/Collections/Debtors are numeric columns 

输出

CompanyCode AccountClass   Type   1 2 3 
----------- -------------------- ------------ ---- ---- ---- 
500   Accounts Receiveable Billings  xx xxx xx 
500   Accounts Receiveable Collections xx xx xx 
500   Accounts Receiveable Debtors  xx xx xxx