【问题标题】:SQL Unpivot multiple columns DataSQL Unpivot 多列数据
【发布时间】:2013-09-04 14:57:46
【问题描述】:

我使用的是 SQL Server 2008,我正在尝试对数据进行反透视。这是我正在使用的 SQL 代码,

CREATE TABLE #pvt1 (VendorID int, Sa int, Emp1 int,Sa1 int,Emp2 int)
GO
INSERT INTO #pvt1  VALUES (1,2,4,3,9);

GO

--Unpivot the table.
SELECT distinct VendorID,Orders,Orders1
FROM 
   (SELECT VendorID, Emp1, Sa,Emp2,Sa1
   FROM #pvt1 ) p
UNPIVOT
   (Orders FOR Emp IN 
      (Emp1,Emp2)
)AS unpvt
UNPIVOT
   (Orders1 FOR Emp1 IN 
      (Sa,Sa1)
)AS unpvt1;
GO

这是上面代码的结果。

VendorID    Orders  Orders1
1            4      2
1            4      3
1            9      2
1            9      3

但我希望我的输出如下所示

VendorID    Orders  Orders1
1           4       2
1           9       3

上面代码的关系是2与4相关,3与9相关。

我怎样才能做到这一点?

【问题讨论】:

标签: sql sql-server sql-server-2008 unpivot


【解决方案1】:

取消透视数据的更简单方法是使用 CROSS APPLY 成对取消透视列:

select vendorid, orders, orders1
from pvt1
cross apply
(
  select emp1, sa union all
  select emp2, sa1
) c (orders, orders1);

SQL Fiddle with Demo。或者,如果您不想使用 UNION ALL,可以将 CROSS APPLY 与 VALUES 子句一起使用:

select vendorid, orders, orders1
from pvt1
cross apply
(
  values 
    (emp1, sa),
    (emp2, sa1)
) c (orders, orders1);

SQL Fiddle with Demo

【讨论】:

  • 哇...这非常有用,但我从来没有打扰过它。我需要尽快了解 CROSS APPLY。
  • 这是非透视代码的绝佳替代品。我喜欢交叉申请!
【解决方案2】:

Taryn 的回答确实超级有用,我想扩展它的一个方面。

如果您有一个像这样的非常未规范化的表,其中包含多组列,例如4 个季度或 12 个月:

+-------+------+------+------+------+------+------+-------+------+
| cYear | foo1 | foo2 | foo3 | foo4 | bar1 | bar2 | bar3  | bar4 |
+-------+------+------+------+------+------+------+-------+------+
|  2020 |   42 |  888 |    0 |   33 | one  | two  | three | four |
+-------+------+------+------+------+------+------+-------+------+

那么 CROSS APPLY 方法很容易编写和理解,当你掌握了它的窍门。对于编号列,使用常量值。

SELECT 
    cYear,
    cQuarter,
    foo,
    bar
FROM temp

CROSS APPLY
(
  VALUES
    (1, foo1, bar1),
    (2, foo2, bar2),
    (3, foo3, bar3),
    (4, foo4, bar4)

) c (cQuarter, foo, bar)

结果:

+-------+----------+-----+-------+
| cYear | cQuarter | foo |  bar  |
+-------+----------+-----+-------+
|  2020 |        1 |  42 | one   |
|  2020 |        2 | 888 | two   |
|  2020 |        3 |   0 | three |
|  2020 |        4 |  33 | four  |
+-------+----------+-----+-------+

SQL Fiddle

【讨论】:

    【解决方案3】:

    我需要复合键并跳过额外行以防数据丢失(NULL)。例如。当 x2 和 y2 是可能的替代供应商和价格时

    WITH pvt AS (SELECT * FROM (VALUES 
       ( 1, 6, 11, 111, 12, 13, 122, 133),
       ( 2, 6, 21, 211, 22, 23, 222, 233),
       ( 3, 6, 31, 311, 32, 33, 322, 333),
       ( 5, 4, 41, 411, 42, NULL, 422, NULL),
       ( 6, 4, 51, 511, 52, NULL, 522, NULL))
       s( id, s, a, b, x1, x2, y1, y2)
    )
    -- SELECT * FROM pvt
    
    SELECT CONCAT('xy_',s,'_', id, postfix) as comp_id, a, b, x, y 
    FROM pvt
    CROSS APPLY
    (
      VALUES
        (NULL, x1, y1),   
        ('_ext', x2, y2)
    
    ) c (postfix, x, y)
    WHERE x IS NOT NULL
    

    生产

    comp_id                          a           b           x           y
    -------------------------------- ----------- ----------- ----------- -----------
    xy_6_1                           11          111         12          122
    xy_6_1_ext                       11          111         13          133
    xy_6_2                           21          211         22          222
    xy_6_2_ext                       21          211         23          233
    xy_6_3                           31          311         32          322
    xy_6_3_ext                       31          311         33          333
    xy_4_5                           41          411         42          422
    xy_4_6                           51          511         52          522
    
    (8 rows affected)
    

    来自:

    id          s           a           b           x1          x2          y1          y2
    ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
    1           6           11          111         12          13          122         133
    2           6           21          211         22          23          222         233
    3           6           31          311         32          33          322         333
    5           4           41          411         42          NULL        422         NULL
    6           4           51          511         52          NULL        522         NULL
    

    (受影响的 5 行)

    【讨论】:

    • 请用一个独立的陈述来介绍您的答案“或者可能是”正在提出替代解决方案,但与什么相反?你指的是另一个答案吗?原来的问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-23
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多