1

我对 SQL 很陌生,不知道如何完成以下任务:我在表中有一组数据,我需要将数据转换为两个值之一,然后将每个值的总数相加一对汇总列中的行。见下文:

表1:

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。

4

2 回答 2

1

您可以使用以下内容对数据进行反透视以获取汽车和卡车的总数。

您可以使用该UNPIVOT函数,但由于您使用的是 SQL Server 2008,因此您可以使用CROSS APPLYandVALUES将您的P1P2P3from 列转换为行。转换数据的代码是:

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 |
于 2013-03-29T18:19:55.850 回答
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;
于 2013-03-29T18:40:58.570 回答