Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server:透视和取消透视_Sql_Sql Server_Pivot - Fatal编程技术网

SQL Server:透视和取消透视

SQL Server:透视和取消透视,sql,sql-server,pivot,Sql,Sql Server,Pivot,我正在尝试透视这个SQL Server表,但是我正在努力思考我需要做什么。我可以做一个基本的支点,但这已经变得非常具有挑战性。我本质上是将下表转换为 Company Code Account Class Period Billings Collections Debtors -------------------------------------------------------------------------------- 500

我正在尝试透视这个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


我计划在一个单独的列上创建一个透视图,然后将表本身连接起来,再次使用表本身执行另一个透视图,但我没有捕获列名。如果您有任何建议,我们将不胜感激。

您的想法是正确的,您需要先
取消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=无效列名)忽略,时间太晚,而且我是个笨蛋,调用了错误的表。谢谢你这么全面的回答。