SQL Unpivot 多列数据
Posted
技术标签:
【中文标题】SQL Unpivot 多列数据【英文标题】:SQL Unpivot multiple columns Data 【发布时间】: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相关。
我怎样才能做到这一点?
【问题讨论】:
FWIW .. 以下链接帮助了我... mangalpardeshi.blogspot.com/2009/04/… 【参考方案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 行)
【讨论】:
请用一个独立的陈述来介绍您的答案“或者可能是”正在提出替代解决方案,但与什么相反?你指的是另一个答案吗?原来的问题?以上是关于SQL Unpivot 多列数据的主要内容,如果未能解决你的问题,请参考以下文章