22

我正在使用 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 相关。

我怎样才能做到这一点?

4

3 回答 3

42

对数据进行反透视的一种更简单的方法是使用 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

于 2013-09-04T15:03:18.410 回答
1

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小提琴

于 2020-10-13T17:31:14.387 回答
0

我需要复合键并跳过额外行以防数据丢失(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 行)

于 2021-03-25T18:02:57.257 回答