SQL Server:透视和取消透视
我正在尝试透视这个SQL Server表,但是我正在努力思考我需要做什么。我可以做一个基本的支点,但这已经变得非常具有挑战性。我本质上是将下表转换为SQL Server:透视和取消透视,sql,sql-server,pivot,Sql,Sql Server,Pivot,我正在尝试透视这个SQL Server表,但是我正在努力思考我需要做什么。我可以做一个基本的支点,但这已经变得非常具有挑战性。我本质上是将下表转换为 Company Code Account Class Period Billings Collections Debtors -------------------------------------------------------------------------------- 500
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
到
我计划在一个单独的列上创建一个透视图,然后将表本身连接起来,再次使用表本身执行另一个透视图,但我没有捕获列名。如果您有任何建议,我们将不胜感激。您的想法是正确的,您需要先
取消PIVOT
,以获得您想要的最终结果。您需要将多个列的账单
、收款
和债务人
转换为多行,然后将期间
值转换为列
您没有指定正在使用的SQL Server版本,但从SQL Server 2005开始,您可以使用交叉应用取消PIVOT:
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);
看。这会将数据转换为以下格式:
| 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 |
您会注意到,现在每个账单
、收款
和债务人都有一行。现在,您可以将PIVOT函数应用于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;
看。这将为您提供以下结果:
| 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 |
现在,如果您有可能在同一期间内公司代码
和会计类
出现多次,则需要创建一个可用于返回多个不同行的值。在这种情况下,您需要使用类似于row\u 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;
| 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) |
看。您会注意到,这会稍微将结果更改为:
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;
| 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) |
请尝试以下方法。首先,您需要取消开票账单
,收款
,以及债务人
,然后调整期间
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
@蓝脚:关键问题!:-)@你打过电话吗?:)看-你知道答案!:-)哇,这是非常全面的。不幸的是,当我尝试应用你的方法时,我得到了错误。我还得进一步研究。@Calgar99你错在哪里?您使用的是哪个版本的SQL Server?MS SQL,我正在尝试应用您提供的第二种方法,但错误是它无法识别任何已预定义的列(即(CompanyCode=无效列名)忽略,时间太晚,而且我是个笨蛋,调用了错误的表。谢谢你这么全面的回答。