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)
执行
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 #人员答题数据,#行数据中的需要转成列标题的数据
以上是关于sql server 行转列的主要内容,如果未能解决你的问题,请参考以下文章