SQL - 转换值,计算跨多个列的实例数

时间:2013-03-29 18:05:21

标签: sql sql-server-2008 unpivot

我是SQL的新手,我不知道如何完成以下任务:我在表中有一组数据,我需要将数据转换为两个值中的一个,然后加起来一对摘要列中每行的总计。见下文:

TBL1:

row    P1    P2    P3
---    ---   ---   ---
1      a     b     c
2      a     a     a
3      b     c     b
4      a     b     b
5      NULL  NULL  NULL

转换表为:

PNum    PType
----    -----
a       car
b       truck
c       car

期望的最终结果:

row    P1    P2    P3    numCars    numTrucks
---    ---   ---   ---   -------    ---------
1      a     b     c     2          1
2      a     a     a     3          0
3      b     c     b     1          2
4      a     b     b     1          2
5      NULL  NULL  NULL  NULL       NULL

获取测试表的代码:

DECLARE @tbl1 TABLE(P1 VARCHAR,P2 VARCHAR,P3 VARCHAR)

INSERT INTO @tbl1
SELECT 'a','b','c' UNION ALL
SELECT 'a','a','a' UNION ALL
SELECT 'b','c','b' UNION ALL
SELECT 'a','b','b'


DECLARE @tbl2 TABLE(PNum VARCHAR,PType NVARCHAR(100))

INSERT INTO @tbl2
SELECT 'a','car' UNION ALL
SELECT 'b','truck' UNION ALL
SELECT 'c','car'

我一直在研究PIVOT,但我很难看到如何实现它,(特别是转换片)。我想尝试首先插入一组列只是为了转换值(例如“P1_converted”),然后尝试总结它们,但我的实际表有10个这些类型的列,我不想添加一个额外的10列如果有一个更简单的方法,到桌子。有什么想法吗?谢谢!

我正在使用SQL Server 2008。

2 个答案:

答案 0 :(得分:1)

您可以使用以下取消数据来获取汽车和卡车的总数。

您可以使用UNPIVOT功能,但由于您使用的是SQL Server 2008,因此可以使用CROSS APPLYVALUES转换P1P2P3从列到行。转换数据的代码是:

select *
from tbl1 
cross apply 
(
  values ('p1', p1), ('p2', p2), ('p3', p3)
) c(col, value)

SQL Fiddle with Demo。这会将数据转换为以下格式:

| P1 | P2 | P3 | COL | VALUE |
------------------------------
|  a |  b |  c |  p1 |     a |
|  a |  b |  c |  p2 |     b |
|  a |  b |  c |  p3 |     c |
|  a |  a |  a |  p1 |     a |

一旦数据在行中,您就可以轻松加入转换表以获取每行的计数:

select rn, p1, p2, p3,
  sum(case when t.ptype = 'car' then 1 else 0 end) numCars,
  sum(case when t.ptype = 'truck' then 1 else 0 end) numTrucks
from
(
  select p1, p2, p3,
    row_number() over(order by p1, p2, p3) rn
  from tbl1
) d
cross apply (values ('p1', p1), ('p2', p2), ('p3', p3)) c(col, value)
inner join tbl2 t
  on c.value = t.pnum
group by rn, p1, p2, p3

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

| RN | P1 | P2 | P3 | NUMCARS | NUMTRUCKS |
-------------------------------------------
|  1 |  a |  a |  a |       3 |         0 |
|  2 |  a |  b |  b |       1 |         2 |
|  3 |  a |  b |  c |       2 |         1 |
|  4 |  b |  c |  b |       1 |         2 |

答案 1 :(得分:1)

使用PIVOT

的方法略有不同
SELECT * FROM 
(
  SELECT d.[row], d.P1, d.P2, d.P3, t.PType,
    [tc] = CASE WHEN t.PNum = d.P1 THEN 1 ELSE 0 END
         + CASE WHEN t.PNum = d.P2 THEN 1 ELSE 0 END
         + CASE WHEN t.PNum = d.P3 THEN 1 ELSE 0 END
  FROM @tbl1 d CROSS JOIN @tbl2 t
) AS x
PIVOT (SUM([tc]) FOR PType IN ([car],[truck])) AS p;