SQL将多行转换为多列

时间:2016-04-14 18:23:28

标签: 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, 19, 'Pot_Two' UNION ALL
Select 40, 20, 'Pot_Three' 

这描述了多个cid一起创建一个底池,例如31和32在底池中,底池ID为18,我们可以在底池中放入任意数量的cid's (最少1和没有最大)

我想要实现的是连续检索花盆和相关的cid,所以我想到使用pivot并尝试了这个:

SELECT * from 
(
    select cid, pid, name
    from @tmp
) x
pivot 
(
    min(cid)
    for pid in ([18],[19],[20])
) p 

但是这会返回以下内容:

name         18     19      20
Pot_One      31     NULL    NULL
Pot_Three    NULL   NULL    40
Pot_Two      NULL   31      NULL

多数民众赞成是错误的,因为第一个有一个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

我已经更改了枢轴以将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

我尝试了几种不同的方法但没有成功,有没有其他方法可以实现这一目标?

由于

2 个答案:

答案 0 :(得分:1)

问题是数据透视表中的min(cid),它不会为您提供所有条目。切换到在pid上旋转,给出多个cid结果。用subidied取代并用cid值替换值,其中result不是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

答案 1 :(得分:1)

这是另一种解决方案。

基本上pot id和pot name是同一个东西的两个名字,它们没有变化,所以基本上18 (Pot_One)应该是相同的东西的足够好的指标,然后你可以在这个指标和之间创建一个双D映射cid值显示它们是否在下面

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 

<强>输出:

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 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