2013-08-16 21 views
2

我不知道这是否会正式被称为支点,但是,我想结果是这样的:分组和交换列和行

+------+---------+------+ 
| Alex | Charley | Liza | 
+------+---------+------+ 
| 213 |  345 | 1 | 
| 23 |  111 | 5 | 
| 42 |  52 | 2 | 
| 323 |   | 5 | 
| 23 |   | 1 | 
| 324 |   | 5 | 
+------+---------+------+ 

我输入的数据是这种形式:

+-----+---------+ 
| Apt | Name | 
+-----+---------+ 
| 213 | Alex | 
| 23 | Alex | 
| 42 | Alex | 
| 323 | Alex | 
| 23 | Alex | 
| 324 | Alex | 
| 345 | Charley | 
| 111 | Charley | 
| 52 | Charley | 
| 1 | Liza | 
| 5 | Liza | 
| 2 | Liza | 
| 5 | Liza | 
| 1 | Liza | 
| 5 | Liza | 
+-----+---------+ 

,因为我有大约100名,我不希望有做一吨的子查询LIK这

select null, null, thirdcolumn from... 
select null, seconcolumn from... 
select firstcolumn from... 

是有没有办法做到这一点PIVOT或以其他方式?

+0

还有一个类似的问题([link](http://stackoverflow.com/questions/18276913/how-to-convert-rows-to-columns)),虽然对于100个名字,可能动态查询就是你的firend 。 –

+0

谢谢!我很想看到这个问题的动态SQL解决方案 –

回答

2

你可以用动态PIVOT做到这一点和ROW_NUMBER()功能:

DECLARE @cols AS VARCHAR(1000), 
     @query AS VARCHAR(8000) 
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(Name) 
        FROM (SELECT DISTINCT Name 
          FROM #test 
         )sub 
        ORDER BY Name 
        FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)') 
        ,1,1,'') 
PRINT @cols 

SET @query = ' 
WITH cte AS (SELECT DISTINCT * 
      FROM #test) 
    ,cte2 AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Apt)RowRank 
      FROM cte) 
SELECT * 
FROM cte2 
PIVOT (max(Apt) for Name in ('[email protected]+')) p 
      ' 
EXEC (@query) 

SQL Fiddle - Distinct List, Specific Order

编辑:如果你不想在列表中是不同的,消除上面的第一CTE,如果你想保持任意次序变化ORDER BY(SELECT 1)

DECLARE @cols AS VARCHAR(1000), 
     @query AS VARCHAR(8000) 
SELECT @cols = STUFF((SELECT ',' + QUOTENAME(Name) 
        FROM (SELECT DISTINCT Name 
          FROM #test 
         )sub 
          ORDER BY Name 
        FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)') 
        ,1,1,'') 
PRINT @cols 

SET @query = ' 
WITH cte AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY Name ORDER BY (SELECT 1))RowRank 
      FROM #test) 
SELECT * 
FROM cte 
PIVOT (max(Apt) for Name in ('[email protected]+')) p 
      ' 
EXEC (@query) 

SQL Fiddle - Full List, Arbitrary Order

最后,如果你不想在你的结果RowRank场,只是在你的SELECT重新使用@cols变量:

SET @query = ' 
WITH cte AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY Name ORDER BY (SELECT 1))RowRank 
      FROM #test) 
SELECT '[email protected]+' 
FROM cte 
PIVOT (max(Apt) for Name in ('[email protected]+')) p 
      ' 
EXEC (@query) 
2

哦,这是一个痛苦的东西,但你可以用SQL来完成。您正试图连接列。

select seqnum, 
     max(case when name = 'Alex' then apt end) as Alex, 
     max(case when name = 'Charley' then apt end) as Charley, 
     max(case when name = 'Liza' then apt end) as Liza 
from (select t.*, row_number() over (partition by name order by (select NULL)) as seqnum 
     from t 
    ) t 
group by seqnum 
order by seqnum; 

作为说明:不保证每个列中的原始排序都是相同的。如您所知,SQL表本质上是无序的,所以您需要一列来指定排序。

要处理多个名字,我会使用查询刚才得到的名单,如:

select distinct 'max(case when name = '''+name+''' then apt end) as '+name+',' 
from t; 

而且结果复制到查询。