将多行转换为多列的SQL语句
我有以下资料:将多行转换为多列的SQL语句,sql,sql-server,sql-server-2014,Sql,Sql Server,Sql Server 2014,我有以下资料: DECLARE @tmp TABLE (cid int, pid int, name varchar(10)) Insert Into @tmp (cid, pid, name) Select 31, 18, 'Pot_One' UNION ALL Select 32, 18, 'Pot_One' UNION ALL Select 31, 19, 'Pot_Two' UNION ALL Select 32, 19, 'Pot_Two' UNION ALL Select 33,
DECLARE @tmp TABLE (cid int, pid int, name varchar(10))
Insert Into @tmp (cid, pid, name)
Select 31, 18, 'Pot_One' UNION ALL
Select 32, 18, 'Pot_One' UNION ALL
Select 31, 19, 'Pot_Two' UNION ALL
Select 32, 19, 'Pot_Two' UNION ALL
Select 33, 19, 'Pot_Two' UNION ALL
Select 40, 20, 'Pot_Three'
name 18 19 20
Pot_One 31 NULL NULL
Pot_Three NULL NULL 40
Pot_Two NULL 31 NULL
这描述了多个cid组合在一起以创建一个pot,例如pot 1中有31个和32个,pot id为18,我们可以在一个pot中有任意数量的cid(最小值为1,最大值为0)
我试图实现的是连续检索pots和相关cid,因此我考虑使用pivot并尝试了以下方法:
SELECT * from
(
select cid, pid, name
from @tmp
) x
pivot
(
min(cid)
for pid in ([18],[19],[20])
) p
但这将返回以下结果:
DECLARE @tmp TABLE (cid int, pid int, name varchar(10))
Insert Into @tmp (cid, pid, name)
Select 31, 18, 'Pot_One' UNION ALL
Select 32, 18, 'Pot_One' UNION ALL
Select 31, 19, 'Pot_Two' UNION ALL
Select 32, 19, 'Pot_Two' UNION ALL
Select 33, 19, 'Pot_Two' UNION ALL
Select 40, 20, 'Pot_Three'
name 18 19 20
Pot_One 31 NULL NULL
Pot_Three NULL NULL 40
Pot_Two NULL 31 NULL
这是错误的,因为pot one中有31和32,这只代表31,我需要的是潜在的:
name 18 18 19 19 19 20
Pot_One 31 32 NULL NULL NULL NULL
Pot_Three NULL NULL NULL NULL NULL 40
Pot_Two NULL NULL 31 32 33 NULL
我已经更改了pivot以将cid作为列标题,并得到了这一点,这更接近我试图实现的目标:
SELECT * from
(
select cid, pid, name
from @tmp
) x
pivot
(
min(pid)
for cid in ([31],[32],[33],[40])
) p
name 31 32 33 40
Pot_One 18 18 NULL NULL
Pot_Three NULL NULL NULL 20
Pot_Two 19 19 19 NULL
我尝试了几种不同的方法,但都没有成功,还有其他方法吗
谢谢问题在于pivot中的min(cid),它不会提供所有条目。切换到在pid上旋转,给出多个cid结果。子查询该值并将其替换为cid值,其中结果不为NULL
DECLARE @tmp TABLE (cid int, pid int, name varchar(10))
Insert Into @tmp (cid, pid, name)
Select 31, 18, 'Pot_One' UNION ALL
Select 32, 18, 'Pot_One' UNION ALL
Select 31, 19, 'Pot_Two' UNION ALL
Select 32, 19, 'Pot_Two' UNION ALL
Select 33, 19, 'Pot_Two' UNION ALL
Select 40, 20, 'Pot_Three'
SELECT name, CASE WHEN [18] IS NOT NULL THEN CID END AS [18], CASE WHEN [19] IS NOT NULL THEN CID END AS [19], CASE WHEN [20] IS NOT NULL THEN CID END AS [20]
FROM
(
SELECT * from
(
select cid, pid, name
from @tmp
) x
pivot
(
min(pid)
for pid in ([18],[19],[20])
) p
) x
这里有一个替代方案 基本上,pot id和pot name是同一事物的两个名称,它们没有变化,因此基本上
18(pot_One)
应该是同一事物的足够好的指示器,然后您可以在该指示器和cid值之间创建两个D映射,以显示它们是否在其中
SELECT * from
(
select cid, cast(pid as varchar) +' ('+ name +')' as name, 1 r
from @tmp
) x
pivot
(
min(r)
for cid in ([31],[32],[33],[40])
) p
SELECT name, ISNULL([31], 'x') [31],ISNULL([32],'x') [32],ISNULL([33],'x') [33],ISNULL([40],'x') [40]
from
(
select cid, cast(pid as varchar) +' ('+ name +')' as name, '1' r
from @tmp
) x
pivot
(
min(r)
for cid in ([31],[32],[33],[40])
) p
输出:
name 31 32 33 40
-------------------------- ----------- ----------- -----------
18 (Pot_One) 1 1 NULL NULL
19 (Pot_Two) 1 1 1 NULL
20 (Pot_Three) NULL NULL NULL 1
此外,您还可以通过如下修改将NULL替换为“X”
SELECT * from
(
select cid, cast(pid as varchar) +' ('+ name +')' as name, 1 r
from @tmp
) x
pivot
(
min(r)
for cid in ([31],[32],[33],[40])
) p
SELECT name, ISNULL([31], 'x') [31],ISNULL([32],'x') [32],ISNULL([33],'x') [33],ISNULL([40],'x') [40]
from
(
select cid, cast(pid as varchar) +' ('+ name +')' as name, '1' r
from @tmp
) x
pivot
(
min(r)
for cid in ([31],[32],[33],[40])
) p
输出
name 31 32 33 40
--------------- ---- ---- ---- ----
18 (Pot_One) 1 1 x x
19 (Pot_Two) 1 1 1 x
20 (Pot_Three) x x x 1
您希望输出是什么样子的?这看起来有点挑战,但也很有趣。你能提供你想要的输出吗?谢谢你的关注。我需要的是能够以某种方式显示cid 31和32在罐18中,cid 31、32和33在罐19中,cid 40在罐20中。@03Usr请检查我的答案。如果你觉得这个问题有用,请接受和/或投票,以便将来有类似问题的求职者发现这个问题有用。[ ]