2013-02-05 107 views
3

我有一个场景,我希望将每个唯一列值(Val2)的列值(Val1)显示为单个列,最多为10列。使用PIVOT将列值选择为列

CREATE TABLE #TEMP1 (Val1 NVARCHAR(4), Val2 NVARCHAR(10)); 

insert into #Temp1 Values ('S01','00731') 
insert into #Temp1 Values ('S02','00731') 
insert into #Temp1 Values ('S03','00731') 
insert into #Temp1 Values ('S04','00731') 
insert into #Temp1 Values ('S05','00731') 
insert into #Temp1 Values ('S06','00731') 
insert into #Temp1 Values ('S07','00731') 
insert into #Temp1 Values ('S08','00731') 
insert into #Temp1 Values ('S09','00731') 
insert into #Temp1 Values ('S07','00731') 
insert into #Temp1 Values ('S04','00741') 
insert into #Temp1 Values ('S01','00746') 
insert into #Temp1 Values ('S01','00770') 
insert into #Temp1 Values ('S01','00771') 
insert into #Temp1 Values ('S02','00771') 

Val1 Val2 
-------------------------- 
S01  00731 
S02  00731 
S03  00731 
S04  00731 
S05  00731 
S06  00731 
S07  00731 
S08  00731 
S09  00731 
S07  00731 
S04  00741 
S01  00746 
S01  00770 
S01  00771 
S02  00771 

然后,我使用数据透视列来显示每个唯一的Val2值,并将最多10个Val1值显示为列。

SELECT [Val2], 
c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 
FROM 
(SELECT Val1, Val2 
FROM   #TEMP1) AS PivotTable 
PIVOT 
(
MAX([PivotTable].[Val1]) 
FOR 
Val1 
IN 
(C1, c2, c3, c4, c5, c6, c7, c8, c9, c10) 
) AS PivotTable; 

我想有这样的结果:

Val2 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 
-------------------------------------------------------------------------------------- 
00731 S01 S02 S03 S04 S05 S06 S07 S08 S09 S07 
00741 S04 NULL NULL NULL NULL NULL NULL NULL NULL NULL 
00746 S01 NULL NULL NULL NULL NULL NULL NULL NULL NULL 
00770 S01 NULL NULL NULL NULL NULL NULL NULL NULL NULL 
00771 S01 S02 NULL NULL NULL NULL NULL NULL NULL NULL 

但我实际上只是得到所有NULL值的列:

Val2 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 
-------------------------------------------------------------------------------------- 
00731 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 
00741 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 
00746 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 
00770 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 
00771 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 
+0

你在误解'PIVOT'是如何工作的(这很奇怪,导致你的问题标题似乎正确地理解了'PIVOT')。透视表的列名称必须是数据的值。在你说'FOR Val1 IN(C1,C2,C3,C4,C5,C6,C7,C8,C9,C10)'的地方,你说Val1列的值是'c1','c2',等等,至少它显然没有,因此你得到NULL值' – Lamak

+0

谢谢拉马克,我现在看到我的错误。也许枢轴不是我的问题在这种情况下正确的解决方案?你能提出一种方法来达到预期的效果吗? – cathalobrien

回答

2

你的要求不完全清楚,但它看起来像您正尝试创建一个名为c的新列,然后与其关联的row_number() - c1, c2 c3, etc

如果你要使用你的子查询如下:

SELECT Val1, Val2, 
    'C'+ cast(row_number() over(partition by Val2 
           order by val1) as varchar(10)) col 
FROM TEMP1 

SQL Fiddle with Demo

你会得到结果:

| VAL1 | VAL2 | COL | 
---------------------- 
| S01 | 00731 | C1 | 
| S02 | 00731 | C2 | 
| S03 | 00731 | C3 | 
| S04 | 00731 | C4 | 
| S05 | 00731 | C5 | 
| S06 | 00731 | C6 | 
| S07 | 00731 | C7 | 
| S07 | 00731 | C8 | 
| S08 | 00731 | C9 | 
| S09 | 00731 | C10 | 
| S04 | 00741 | C1 | 
| S01 | 00746 | C1 | 
| S01 | 00770 | C1 | 
| S01 | 00771 | C1 | 
| S02 | 00771 | C2 | 

这似乎是你的结果,那么想要PIVOT。然后,您可以应用PIVOT这个使用:

SELECT Val2, 
    c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 
FROM 
(
    SELECT Val1, Val2, 
    'C'+ cast(row_number() over(partition by Val2 
           order by val1) as varchar(10)) col 
    FROM TEMP1 
) src 
PIVOT 
(
    MAX(Val1) 
    FOR col IN (C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) 
) piv; 

SQL Fiddle with Demo。你最终的结果则是:

| VAL2 | C1 |  C2 |  C3 |  C4 |  C5 |  C6 |  C7 |  C8 |  C9 | C10 | 
------------------------------------------------------------------------------------------------ 
| 00731 | S01 | S02 | S03 | S04 | S05 | S06 | S07 | S07 | S08 | S09 | 
| 00741 | S04 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 
| 00746 | S01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 
| 00770 | S01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 
| 00771 | S01 | S02 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 

注:我的结果是从你所要求的期望的结果,因为我执行ORDER BY val1这将导致S07值组合在一起略有不同。

除非您请求一个数据库,否则数据库中没有数据顺序,因此不能保证其中一个S07值将显示为C10。你可以使用下面的方法得到的结果,但有不能保证,其结果永远是正确的顺序:

SELECT Val2, 
    c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 
FROM 
(
    SELECT Val1, Val2, 
    'C'+ cast(row_number() over(partition by Val2 
           order by (select 1)) as varchar(10)) col 
    FROM TEMP1 
) src 
PIVOT 
(
    MAX(Val1) 
    FOR col IN (C1, C2, C3, C4, C5, C6, C7, C8, C9, C10) 
) piv; 

SQL Fiddle with Demo。使用order by (select 1)会改变数据的顺序,但不能保证数据总是按顺序排列。其结果是:

| VAL2 | C1 |  C2 |  C3 |  C4 |  C5 |  C6 |  C7 |  C8 |  C9 | C10 | 
------------------------------------------------------------------------------------------------ 
| 00731 | S01 | S02 | S03 | S04 | S05 | S06 | S07 | S08 | S09 | S07 | 
| 00741 | S04 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 
| 00746 | S01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 
| 00770 | S01 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 
| 00771 | S01 | S02 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 
1

你可以尝试创建通过使用相关子查询交叉表或透视的标准方法,和(a CTE内这里)使用排序功能来确定把它列在你的价值观:

;with cte as (
    select Val1 
     , Val2 
     , row_number() over (partition by Val2 order by Val1) as col 
     --, row_number() over (partition by Val2 order by Id) as col -- Use this if you have an identity 
    from #TEMP1 
    --from (select distinct * from #TEMP1) as t -- Use this to rank distinct entries 
) 
select c.Val2 
    , (select Val1 from cte where Val2 = c.Val2 and col = 1) as c1 
    , (select Val1 from cte where Val2 = c.Val2 and col = 2) as c2 
    , (select Val1 from cte where Val2 = c.Val2 and col = 3) as c3 
    , (select Val1 from cte where Val2 = c.Val2 and col = 4) as c4 
    , (select Val1 from cte where Val2 = c.Val2 and col = 5) as c5 
    , (select Val1 from cte where Val2 = c.Val2 and col = 6) as c6 
    , (select Val1 from cte where Val2 = c.Val2 and col = 7) as c7 
    , (select Val1 from cte where Val2 = c.Val2 and col = 8) as c8 
    , (select Val1 from cte where Val2 = c.Val2 and col = 9) as c9 
    , (select Val1 from cte where Val2 = c.Val2 and col = 10) as c10 
from cte as c 
group by c.Val2 
order by c.Val2 

注意,有一些方法来确定哪些列Val2所属,我已经把一对夫妇的可能性在CTE(一些评论)。但是,由于目前还没有办法说明S07应该在第十列中,所以您当前的期望输出无法达到。如果这是你想要的,也许在临时表中添加一个身份将会捕获事件的顺序。我也在CTE中包含了这种可能性。