我是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。
答案 0 :(得分:1)
您可以使用以下取消数据来获取汽车和卡车的总数。
您可以使用UNPIVOT
功能,但由于您使用的是SQL Server 2008,因此可以使用CROSS APPLY
和VALUES
转换P1
,P2
和P3
从列到行。转换数据的代码是:
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;