sql server 行转列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql server 行转列相关的知识,希望对你有一定的参考价值。

_key _value id
ceshi 测试值 10
ceshi 测试值 11
ceshi2 测试值2 10

想变成

id ceshi ceshi2
10 测试值 测试值2
11 测试值

求一个灵活的方法 不要写死。。

创建测试表

create table test
(_key varchar(10),
_value varchar(10),
id int)

insert into test values (\'ceshi\',\'测试值\',10)
insert into test values (\'ceshi\',\'测试值\',11)
insert into test values (\'ceshi2\',\'测试值2\',11)

执行

declare @sql varchar(4000)
set @sql = \'select id\'
select @sql = @sql + \',max(case _key when \'\'\'+[_key]+\'\'\' then [_value] end) as 
[\'+_key+\']\'
from (select distinct _key from test) as a
select @sql = @sql+\' from test group by id\'
exec(@sql)

结果


额,我那个第三条数据id写错了,不过方法还是这个

参考技术A 动态行列转换处理

CREATE TABLE TestRowCol (
  name   VARCHAR(10),
  place VARCHAR(10),
  valuw INT
);
INSERT INTO TestRowCol VALUES ('张三', '东', 1);
INSERT INTO TestRowCol VALUES ('张三', '南', 2);
INSERT INTO TestRowCol VALUES ('张三', '西', 3);
INSERT INTO TestRowCol VALUES ('张三', '北', 4);
INSERT INTO TestRowCol VALUES ('李四', '东', 5);
INSERT INTO TestRowCol VALUES ('李四', '南', 6);
INSERT INTO TestRowCol VALUES ('李四', '西', 7);
INSERT INTO TestRowCol VALUES ('李四', '北', 8);

动态的 行列转换,要求 sql 语句中,不能有  东南西北  这样的标题字符.
 


  
使用 CASE WHEN 方式的动态处理.
BEGIN
  -- 主 SQL.
  DECLARE @MainSql  varchar(2000);
  -- 产生动态列的 SQL.
  DECLARE @ColumnSql  varchar(1000);
  -- 设置 产生动态列的 SQL.
  SET @ColumnSql =
    (
      SELECT
        ', SUM(CASE WHEN place = ''' + place + ''' THEN valuw ELSE 0 END) AS ' + place
      FROM
        TestRowCol
      GROUP BY
        place
      FOR XML PATH('')
    );
  -- 设置主 SQL.
  SET @MainSql =
    'SELECT name ' + @ColumnSql + ' FROM TestRowCol GROUP BY name';
  -- 执行主 SQL.
  EXECUTE  ( @MainSql );
END
GO
name       北           东           南           西
---------- ----------- ----------- ----------- -----------
李四                   8           5           6           7
张三                   4           1           2           3
 


   
使用 PIVOT 方式的动态处理.
BEGIN
  -- 主 SQL.
  DECLARE @MainSql  varchar(2000);
  -- 产生动态列的 SQL.
  DECLARE @ColumnSql  varchar(1000);
  -- 设置 产生动态列的 SQL.
  SET @ColumnSql =
    STUFF(
      (
        SELECT
          ',' + place
        FROM
          TestRowCol
        GROUP BY
          place
        FOR XML PATH('')
      ), 1, 1, '');
  -- 设置主 SQL.
  SET @MainSql =
    'SELECT * FROM TestRowCol '
    + ' PIVOT( SUM(valuw) FOR place IN ( '
    + @ColumnSql
    + ' ) ) tmp ORDER BY name';
  -- 执行主 SQL.
  EXECUTE  ( @MainSql );
END
GO
 
name       北           东           南           西
---------- ----------- ----------- ----------- -----------
李四                   8           5           6           7
张三                   4           1           2           3
(2 行受影响)

参考技术B select * from a_tb pivot(max(_value) for _key in(ceshi,ceshi2))a

其中for _key in(ceshi,ceshi2)是你做为列名的字段,比如你现在用_key作为列名,就写for _key in(ceshi,ceshi2),要是_value就写for _value in(测试值,测试值2),注意max里面和for后面字段不要重复,否则会重复显示
参考技术C 用select case when进行行列转换。 参考技术D 网上很多代码的,自己找把

sql server 动态行转列

有时会需要sql结果集行转列的功能

sql的行转列(PIVOT)与列转行(UNPIVOT) 请参照 https://www.cnblogs.com/linJie1930906722/p/6036714.html

但是有时需要动态列 而且展示的数据部分是字符串 用上面的方法就不好使了

比如想把下面图片中 的 上半部分 行转列成 下半部分

技术分享图片

 

sql 如下

但是因为是exec执行 select into 不行 insert select 做起来也比较麻烦只能用到最后的返回结果

如果并发查询不严重 可以插入一个专门存放数据的表 不是临时表 用完就删

要么就先建好临时表 拼sql动态插入列 没试过这种方式 不知道好使不

 

 

技术分享图片
--基础数据 即需要行转列的数据
CREATE TABLE #人员答题数据
    (
      人员姓名 NVARCHAR(50) NULL ,
      题目名称 NVARCHAR(50) NULL ,
      所答结果 NVARCHAR(50) NULL
    )
INSERT  INTO #人员答题数据
        ( 人员姓名 ,
          题目名称 ,
          所答结果
        )
        SELECT  张三 ,
                题目1 ,
                张三题目1答案
        UNION
        SELECT  张三 ,
                题目2 ,
                张三题目2答案
        UNION
        SELECT  张三 ,
                题目3 ,
                张三题目3答案
        UNION
        SELECT  李四 ,
                题目1 ,
                李四题目1答案
        UNION
        SELECT  李四 ,
                题目2 ,
                李四题目2答案
        UNION
        SELECT  李四 ,
                题目3 ,
                李四题目3答案

SELECT * FROM #人员答题数据  ORDER BY  人员姓名,题目名称

--拼接最后的select 列数据用 如果基础数据中 的列标题是全部完整的 也可以从基础数据distinct
CREATE  TABLE #行数据中的需要转成列标题的数据 ( 题目名称 NVARCHAR(200) NULL )

INSERT  INTO #行数据中的需要转成列标题的数据
        SELECT DISTINCT
                题目名称
        FROM    #人员答题数据
        
DECLARE @sql拼接最终列 NVARCHAR(MAX)= ‘‘              
SET @sql拼接最终列 = ‘‘              
SELECT  @sql拼接最终列+= ISNULL(MAX(CASE 题目名称 WHEN ‘‘‘ + 题目名称
        + ‘‘‘ THEN 所答结果 END  ),‘‘‘‘) AS [ + 题目名称 + ],
FROM    #行数据中的需要转成列标题的数据             
 
--多了一个, 去掉         
IF ( @sql拼接最终列 != ‘‘ )
    BEGIN          
        SET @sql拼接最终列 = @sql拼接最终列 + $          
        SET @sql拼接最终列 = REPLACE(@sql拼接最终列, ,$, ‘‘)          
    END          
  
  
DECLARE @sql NVARCHAR(MAX)
SET @sql = SELECT 人员姓名,  + @sql拼接最终列                       
SET @sql +=  FROM    #人员答题数据  GROUP BY 人员姓名 
  
EXEC(@sql)              
PRINT ( @sql )   
  
DROP TABLE #人员答题数据,#行数据中的需要转成列标题的数据
View Code

 

以上是关于sql server 行转列的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 动态行转列(参数化表名分组列行转列字段字段值)

SQL Server行转列

sql server 行转列

sql server 动态行转列

mysql行转列转换

SQL server 行转列 列转行