透视数百万条记录

时间:2013-05-08 16:32:56

标签: sql-server pivot

我有一个包含4列和超过1亿条记录的表格。 表设计:

ID char(12) PK 
Type Char(2) PK (Values 1,2,3)
DCID varchar(10) Null
IND Varchar(2) Null (Values Y, N)

这需要像

一样进行转动
ID, DCID1, DCID2, DCID3, IND1, IND2, IND3

如果Type的值为1,那么在Pivoted表中,DCID1应该具有值,或者Type为2 DCID2应该具有值,依此类推。此外,还需要将IND替换为IND1IND2IND3

如何转动这个?

2 个答案:

答案 0 :(得分:5)

我的建议是看看使用UNPIVOT和PIVOT函数来获得结果。

UNPIVOT将用于将DCIIND多个列转换为单个列中的多个行。完成后,您可以将数据转回到列中。

UNPIVOT代码与此类似:

select id,
  col +type as new_col,
  value
from
(
  select id,
    type, 
    dcid, 
    cast(ind as varchar(10)) ind
  from yt
) d
unpivot
(
  value
  for col in (DCID, IND)
) unpiv;

SQL Fiddle with Demo。这给出了一个结果:

|           ID | NEW_COL | VALUE |
----------------------------------
| 1            |  dcid1  |  test |
| 1            |   ind1  |     Y |
| 2            |  dcid2  |   est |
| 2            |   ind2  |     Y |

new_col包含DCIDIND个名称,并且type值连接到最后。这个新值将是您将PIVOT应用于:

select id, DCID1, DCID2, DCID3, IND1, IND2, IND3
from
(
  select id,
    col +type as new_col,
    value
  from
  (
    select id,
      type, 
      dcid, 
      cast(ind as varchar(10)) ind
    from yt
  ) d
  unpivot
  (
    value
    for col in (DCID, IND)
  ) unpiv
) src
pivot
(
  max(value)
  for new_col in (DCID1, DCID2, DCID3, IND1, IND2, IND3)
) piv;

SQL Fiddle with Demo。结果将是:

|           ID | DCID1 | DCID2 | DCID3 | IND1 | IND2 | IND3 |
-------------------------------------------------------------
| 1            |  test |       |       |    Y |      |      |
| 2            |       |   est |       |      |    Y |      |
| 3            |       |       |  blah |      |      |    Y |
| 4            |   yes |       |       |    N |      |      |
| 5            |       |    hs |       |      |    N |      |
| 6            |       |       |    jr |      |      |    N |

答案 1 :(得分:5)

如果源数据如下所示:

+----+------+------+-----+
| ID | TYPE | DCID | IND |
+----+------+------+-----+
|  1 |    1 | test | Y   |
|  1 |    2 | est  | Y   |
|  1 |    3 | blah | Y   |
|  2 |    1 | yes  | N   |
|  2 |    2 | hs   | N   |
|  2 |    3 | jr   | N   |
+----+------+------+-----+

所需的输出是:

+-------+-------+-------+------+------+------+
| DCID1 | DCID2 | DCID3 | IND1 | IND2 | IND3 |
+-------+-------+-------+------+------+------+
| test  | est   | blah  | Y    | Y    | Y    |
| yes   | hs    | jr    | N    | N    | N    |
+-------+-------+-------+------+------+------+

一个解决方案是(SQLfiddle):

SELECT
  DCID1 = MAX(CASE WHEN type = '1' THEN dcid ELSE NULL END),
  DCID2 = MAX(CASE WHEN type = '2' THEN dcid ELSE NULL END),
  DCID3 = MAX(CASE WHEN type = '3' THEN dcid ELSE NULL END),
  IND1 = MAX(CASE WHEN type = '1' THEN ind ELSE NULL END),
  IND2 = MAX(CASE WHEN type = '2' THEN ind ELSE NULL END),
  IND3 = MAX(CASE WHEN type = '3' THEN ind ELSE NULL END)
FROM yt
GROUP BY id
ORDER BY id;

execution plan