--还是看这个好了:
*
标题:普通行列转换(version 2.0)
作者:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)
时间:2008-03-09
地点:广东深圳
说明:普通行列转换(version 1.0)仅针对sql server 2000提供静态和动态写法,version 2.0增加sql server 2005的有关写法。问题:假设有张学生成绩表(tb)如下:
姓名 课程 分数
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
李四 物理 94
想变成(得到如下结果): 
姓名 语文 数学 物理 
---- ---- ---- ----
李四 74   84   94
张三 74   83   93
-------------------
*/create table tb(姓名 varchar(10) , 课程 varchar(10) , 分数 int)
insert into tb values('张三' , '语文' , 74)
insert into tb values('张三' , '数学' , 83)
insert into tb values('张三' , '物理' , 93)
insert into tb values('李四' , '语文' , 74)
insert into tb values('李四' , '数学' , 84)
insert into tb values('李四' , '物理' , 94)
go--SQL SERVER 2000 静态SQL,指课程只有语文、数学、物理这三门课程。(以下同)
select 姓名 as 姓名 ,
  max(case 课程 when '语文' then 分数 else 0 end) 语文,
  max(case 课程 when '数学' then 分数 else 0 end) 数学,
  max(case 课程 when '物理' then 分数 else 0 end) 物理
from tb
group by 姓名--SQL SERVER 2000 动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from tb) as a
set @sql = @sql + ' from tb group by 姓名'
exec(@sql) --SQL SERVER 2005 静态SQL。
select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + '],[' , '') + 课程 from tb group by 课程
set @sql = '[' + @sql + ']'
exec ('select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b')

解决方案 »

  1.   

    ---------------------------------
    --  Author: liangCK 小梁
    --  Date  : 2009-05-20 15:15:08
    ---------------------------------
     
    --> 生成测试数据: #T
    IF OBJECT_ID('tempdb.dbo.#T') IS NOT NULL DROP TABLE #T
    CREATE TABLE #T (item INT,value VARCHAR(2))
    INSERT INTO #T
    SELECT 1,'11' UNION ALL
    SELECT 1,'22' UNION ALL
    SELECT 1,'33' UNION ALL
    SELECT 3,'aa' UNION ALL
    SELECT 3,'bb' UNION ALL
    SELECT 3,'cc' UNION ALL
    SELECT 11,'!!' UNION ALL
    SELECT 11,'@@'--SQL查询如下:DECLARE @sql VARCHAR(MAX);
    SET @sql='';SELECT 
        @sql=@sql+',['+RTRIM(item)+']'
    FROM (SELECT DISTINCT item FROM #T) AS T;SET @sql=STUFF(@sql,1,1,'');EXEC('
        SELECT '+@sql+'
        FROM (
            SELECT rowid=ROW_NUMBER() OVER(PARTITION BY item ORDER BY [value]),
                   item,[value]
            FROM #T
        ) AS A
            PIVOT(MAX([value]) FOR item IN('+@sql+')) AS pvt
    ')
    /*
    1    3    11
    ---- ---- ----
    11   aa   !!
    22   bb   @@
    33   cc   NULL(3 row(s) affected)*/
      

  2.   

    行转出来的是这样的。
                      Set @iSQL='Select ' +@iItem+'
    from #Diagnose_Item
    PIVOT
    (
    MAX(VALUE)
    for StationItem In('+@iItem+')
    ) as pvt'
                    exec(@iSQL)
    只能出表结构啊。
      

  3.   


    Set @iSQL='Select ' +@iItem+' 
    from #Diagnose_Item 
    PIVOT 

    MAX(VALUE) 
    for StationItem In('+@iItem+') 
    ) as pvt' 
    exec(@iSQL) 只能把最大的搞到表里面啊。
    那样我还要根据syscolumns找他的列名,再根据列名更新,实在很麻烦啊。
    而且数据也不少。
      

  4.   

    create table t(item int,value varchar(10))
    insert into t select  1,'11'
    insert into t select  1,'22'
    insert into t select  1,'33'
    insert into t select  3,'aa'
    insert into t select  3,'bb'
    insert into t select  3,'cc'
    insert into t select 11,'!!'
    insert into t select 11,'@@'
    godeclare @sql varchar(8000)
    select @sql=isnull(@sql,'')+',['+rtrim(item)+']=max(case item when '+rtrim(item)+' then [value] end)' 
    from (select distinct item from t) aset @sql='select '+stuff(@sql,1,1,'')+
             ' from (select a.*,(select count(1) from t where item=a.item and [value]<=a.[value]) as id from t a) r group by id'exec(@sql)
    /*
    1          3          11         
    ---------- ---------- ---------- 
    11         aa         !!
    22         bb         @@
    33         cc         NULL
    */
    godrop table t
    go
      

  5.   

    CREATE TABLE TB([item] VARCHAR(2), [value] VARCHAR(2))
    INSERT TB 
    SELECT '1', '11' UNION ALL 
    SELECT '1', '22' UNION ALL 
    SELECT '1', '33' UNION ALL 
    SELECT '3', 'aa' UNION ALL 
    SELECT '3', 'bb' UNION ALL 
    SELECT '3', 'cc' UNION ALL 
    SELECT '11', '!!' UNION ALL 
    SELECT '11', '@@'SELECT *,SEQ=ROW_NUMBER() OVER (PARTITION BY item ORDER BY GETDATE())
    INTO TC
    FROM TB DECLARE @STR VARCHAR(8000),@STR2 VARCHAR(8000),@STR3 VARCHAR(8000)
    SET @STR=''
    SET @STR2=''
    SET @STR3=''SELECT @STR=@STR+','+'(SELECT value FROM TC WHERE SEQ=1 AND item='''+item+''') AS ['+item+']',
       @STR2=@STR2+','+'(SELECT value FROM TC WHERE SEQ=2 AND item='''+item+''') AS ['+item+']',
       @STR3=@STR3+','+'(SELECT value FROM TC WHERE SEQ=3 AND item='''+item+''') AS ['+item+']'
    FROM TB
    GROUP BY itemSET @STR=STUFF(@STR,1,1,'')
    SET @STR2=STUFF(@STR2,1,1,'')
    SET @STR3=STUFF(@STR3,1,1,'')EXEC('SELECT '+@STR+' UNION ALL SELECT '+@STR2+' UNION ALL SELECT '+@STR3)DROP TABLE TB,TC
    /*
    1    11   3
    ---- ---- ----
    11   !!   aa
    22   @@   bb
    33   NULL cc
    */
      

  6.   

    CREATE TABLE TB([item] VARCHAR(2), [value] VARCHAR(2))
    INSERT TB 
    SELECT '1', '11' UNION ALL 
    SELECT '1', '22' UNION ALL 
    SELECT '1', '33' UNION ALL 
    SELECT '3', 'aa' UNION ALL 
    SELECT '3', 'bb' UNION ALL 
    SELECT '3', 'cc' UNION ALL 
    SELECT '11', '!!' UNION ALL 
    SELECT '11', '@@'SELECT *,SEQ=ROW_NUMBER() OVER (PARTITION BY item ORDER BY GETDATE())
    INTO TC
    FROM TBDECLARE @STR VARCHAR(8000)
    SET @STR=''SELECT @STR=@STR+','+'MAX(CASE WHEN item='''+item+''' THEN value END) AS ['+item+']'
    FROM TB
    GROUP BY item SET @STR=STUFF(@STR,1,1,'')EXEC('SELECT '+@STR+' FROM TC GROUP BY SEQ')DROP TABLE TB,TC
    /*
    1    11   3
    ---- ---- ----
    11   !!   aa
    22   @@   bb
    33   NULL cc
    */
      

  7.   

    还有点问题,item里居然有 [] 这种符号,怎么办啊?
      

  8.   

    那就用双引号select 'abc' as "测试[abc]123"
    /**测试[abc]123 
    ---------- 
    abc(所影响的行数为 1 行)
    **/
      

  9.   

    不行吧?
    item是这样的aa[fre],cc,bb[qqq]
    通过sql找出来的列名会变成[aa[fre],[cc]两个字段成立一个字段了。
      

  10.   

    CREATE TABLE TB([item] VARCHAR(10), [value] VARCHAR(2))
    INSERT TB 
    SELECT 'aa[fre]', '11' UNION ALL 
    SELECT 'aa[fre]', '22' UNION ALL 
    SELECT 'aa[fre]', '33' UNION ALL 
    SELECT '3', 'aa' UNION ALL 
    SELECT '3', 'bb' UNION ALL 
    SELECT '3', 'cc' UNION ALL 
    SELECT 'bb[qqq] ', '!!' UNION ALL 
    SELECT 'bb[qqq] ', '@@'SELECT *,SEQ=ROW_NUMBER() OVER (PARTITION BY item ORDER BY GETDATE())
    INTO TC
    FROM TBDECLARE @STR VARCHAR(8000)
    SET @STR=''SELECT @STR=@STR+','+'MAX(CASE WHEN item='''+item+''' THEN value END) AS "'+item+'"'
    FROM TB
    GROUP BY item SET @STR=STUFF(@STR,1,1,'')EXEC('SELECT '+@STR+' FROM TC GROUP BY SEQ')DROP TABLE TB,TC
    /*
    3    aa[fre] bb[qqq] 
    ---- ------- --------
    aa   11      !!
    bb   22      @@
    cc   33      NULL
    */
      

  11.   

    quotename:SQL2005关于quotename的用法 
    首先,sqlserver里的标识符有一定的规则,比如  你 
    create table abc 123(...) 
    那么中间含有空格,它不是符合规则的。 你会写做 create table [abc 123](....) 
    即以[]来定界标识符。quotename将 字串成为有效的标识符。 它有什么用呢? 我举个例子:
    你有个表名字叫做 aa[]bb 当某些应用动态语句查询时 你如何写呢 
    exec('select * from aa[]bb') ?Xset @sql='select * from ' + quotename('aa[]bb') 
    exec(@sql) 当然你也可以直接写出转义的写法 select * from [aa[]]bb] 也就是说,quotename 使函数中的输入成为一个有效的标识符。 
    比如上例中 aa[]bb 不是一个有效的标识符。还有一点就是quotename函数有几种写法: 
      quotename('aa') 生成的有效的标识符为 [aa] 
      quotename('aa','') 生成的有效的标识符为 [aa] 
      quotename('aa','''') 生成的有效的标识符为 'aa'