SQL Server 动态行转列(轉載)

一.本文所涉及的内容(Contents)

  本文所涉及的内容(Contents)

  背景(Contexts)

  实现代码(SQL Codes)

  方法一:使用拼接SQL,静态列字段;

  方法二:使用拼接SQL,动态列字段;

  方法三:使用PIVOT关系运算符,静态列字段;

  方法四:使用PIVOT关系运算符,动态列字段;

  二.背景(Contexts)

  其实行转列并不是一个什么新鲜的话题了,甚至已经被大家说到烂了,网上的很多例子多多少少都有些问题,所以我希望能让大家快速的看到执行的效果,所以在动态列的基础上再把表、分组字段、行转列字段、值这四个行转列固定需要的值变成真正意义的参数化,大家只需要根据自己的环境,设置参数值,马上就能看到效果了(可以直接跳转至:“参数化动态PIVOT行转列”查看具体的脚本代码)。行转列的效果图如图1所示:

  (图1:行转列效果图)

  三.实现代码(SQL Codes)

  (一) 首先我们先创建一个测试表,往里面插入测试数据,返回表记录如图2所示:

  --创建测试表

  IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N‘[dbo].[TestRows2Columns]‘) AND type in (N‘U‘))

  DROP TABLE [dbo].[TestRows2Columns]

  GO

  CREATE TABLE [dbo].[TestRows2Columns](

  [Id] [int] IDENTITY(1,1) NOT NULL,

  [UserName] [nvarchar](50) NULL,

  [Subject] [nvarchar](50) NULL,

  [Source] [numeric](18, 0) NULL

  ) ON [PRIMARY]

  GO

  --插入测试数据

  INSERT INTO [TestRows2Columns] ([UserName],[Subject],[Source])

  SELECT N‘张三‘,N‘语文‘,60 UNION ALL

  SELECT N‘李四‘,N‘数学‘,70 UNION ALL

  SELECT N‘王五‘,N‘英语‘,80 UNION ALL

  SELECT N‘王五‘,N‘数学‘,75 UNION ALL

  SELECT N‘王五‘,N‘语文‘,57 UNION ALL

  SELECT N‘李四‘,N‘语文‘,80 UNION ALL

  SELECT N‘张三‘,N‘英语‘,100

  GO

  SELECT * FROM [TestRows2Columns]

  (图2:样本数据)

  (二) 先以静态的方式实现行转列,效果如图3所示:

  --1:静态拼接行转列

  SELECT [UserName],

  SUM(CASE [Subject] WHEN ‘数学‘ THEN [Source] ELSE 0 END) AS ‘[数学]‘,

  SUM(CASE [Subject] WHEN ‘英语‘ THEN [Source] ELSE 0 END) AS ‘[英语]‘,

  SUM(CASE [Subject] WHEN ‘语文‘ THEN [Source] ELSE 0 END) AS ‘[语文]‘

  FROM [TestRows2Columns]

  GROUP BY [UserName]

  GO

  (图3:样本数据)

  (三) 接着以动态的方式实现行转列,这是使用拼接SQL的方式实现的,所以它适用于SQL Server 2000以上的数据库版本,执行脚本返回的结果如图2所示;

  --2:动态拼接行转列

  DECLARE @sql VARCHAR(8000)

  SET @sql = ‘SELECT [UserName],‘

  SELECT @sql = @sql + ‘SUM(CASE [Subject] WHEN ‘‘‘+[Subject]+‘‘‘ THEN [Source] ELSE 0 END) AS ‘‘‘+QUOTENAME([Subject])+‘‘‘,‘

  FROM (SELECT DISTINCT [Subject] FROM [TestRows2Columns]) AS a

  SELECT @sql = LEFT(@sql,LEN(@sql)-1) + ‘ FROM [TestRows2Columns] GROUP BY [UserName]‘

  PRINT(@sql)

  EXEC(@sql)

  GO

  (四) 在SQL Server 2005之后有了一个专门的PIVOT 和 UNPIVOT 关系运算符做行列之间的转换,下面是静态的方式实现的,实现效果如图4所示:

  --3:静态PIVOT行转列

  SELECT *

  FROM ( SELECT [UserName] ,

  [Subject] ,

  [Source]

  FROM [TestRows2Columns]

  ) p PIVOT

  ( SUM([Source]) FOR [Subject] IN ( [数学],[英语],[语文] ) ) AS pvt

  ORDER BY pvt.[UserName];

  GO

  (图4)

  (五) 把上面静态的SQL基础上进行修改,这样就不用理会记录里面存储了什么,需要转成什么列名的问题了,脚本如下,效果如图4所示:

  --4:动态PIVOT行转列

  DECLARE @sql_str VARCHAR(8000)

  DECLARE @sql_col VARCHAR(8000)

  SELECT @sql_col = ISNULL(@sql_col + ‘,‘,‘‘) + QUOTENAME([Subject]) FROM [TestRows2Columns] GROUP BY [Subject]

  SET @sql_str = ‘

  SELECT * FROM (

  SELECT [UserName],[Subject],[Source] FROM [TestRows2Columns]) p PIVOT

  (SUM([Source]) FOR [Subject] IN ( ‘+ @sql_col +‘) ) AS pvt

  ORDER BY pvt.[UserName]‘

  PRINT (@sql_str)

  EXEC (@sql_str)

  (六) 也许很多人到了上面一步就够了,但是你会发现,当别人拿到你的代码,需要不断的修改成他自己环境中表名、分组列、行转列字段、字段值这几个参数,逻辑如图5所示,所以,我继续对上面的脚本进行修改,你只要设置自己的参数就可以实现行转列了,效果如图4所示:

  --5:参数化动态PIVOT行转列

  -- =============================================

  -- Author: <听风吹雨>

  -- Create date: <2014.05.26>

  -- Description: <参数化动态PIVOT行转列>

  -- Blog:

  -- =============================================

  DECLARE @sql_str NVARCHAR(MAX)

  DECLARE @sql_col NVARCHAR(MAX)

  DECLARE @tableName SYSNAME --行转列表

  DECLARE @groupColumn SYSNAME --分组字段

  DECLARE @row2column SYSNAME --行变列的字段

  DECLARE @row2columnValue SYSNAME --行变列值的字段

  SET @tableName = ‘TestRows2Columns‘

  SET @groupColumn = ‘UserName‘

  SET @row2column = ‘Subject‘

  SET @row2columnValue = ‘Source‘

  --从行数据中获取可能存在的列

  SET @sql_str = N‘

  SELECT @sql_col_out = ISNULL(@sql_col_out + ‘‘,‘‘,‘‘‘‘) + QUOTENAME([‘[email protected]+‘])

  FROM [‘[email protected]+‘] GROUP BY [‘[email protected]+‘]‘

  --PRINT @sql_str

  EXEC sp_executesql @sql_str,N‘@sql_col_out NVARCHAR(MAX) OUTPUT‘,@[email protected]_col OUTPUT

  --PRINT @sql_col

  SET @sql_str = N‘

  SELECT * FROM (

  SELECT [‘[email protected]+‘],[‘[email protected]+‘],[‘[email protected]+‘] FROM [‘[email protected]+‘]) p PIVOT

  (SUM([‘[email protected]+‘]) FOR [‘[email protected]+‘] IN ( ‘+ @sql_col +‘) ) AS pvt

  ORDER BY pvt.[‘[email protected]+‘]‘

  --PRINT (@sql_str)

  EXEC (@sql_str)

  (图5)

  (七) 在实际的运用中,我经常遇到需要对基础表的数据进行筛选后再进行行转列,那么下面的脚本将满足你这个需求,效果如图6所示:

  --6:带条件查询的参数化动态PIVOT行转列

  -- =============================================

  -- Author: <听风吹雨>

  -- Create date: <2014.05.26>

  -- Description: <参数化动态PIVOT行转列,带条件查询的参数化动态PIVOT行转列>

  -- Blog:

  -- =============================================

  DECLARE @sql_str NVARCHAR(MAX)

  DECLARE @sql_col NVARCHAR(MAX)

  DECLARE @sql_where NVARCHAR(MAX)

  DECLARE @tableName SYSNAME --行转列表

  DECLARE @groupColumn SYSNAME --分组字段

  DECLARE @row2column SYSNAME --行变列的字段

  DECLARE @row2columnValue SYSNAME --行变列值的字段

  SET @tableName = ‘TestRows2Columns‘

  SET @groupColumn = ‘UserName‘

  SET @row2column = ‘Subject‘

  SET @row2columnValue = ‘Source‘

  SET @sql_where = ‘WHERE UserName = ‘‘王五‘‘‘

  --从行数据中获取可能存在的列

  SET @sql_str = N‘

  SELECT @sql_col_out = ISNULL(@sql_col_out + ‘‘,‘‘,‘‘‘‘) + QUOTENAME([‘[email protected]+‘])

  FROM [‘[email protected]+‘] ‘[email protected]_where+‘ GROUP BY [‘[email protected]+‘]‘

  --PRINT @sql_str

  EXEC sp_executesql @sql_str,N‘@sql_col_out NVARCHAR(MAX) OUTPUT‘,@[email protected]_col OUTPUT

  --PRINT @sql_col

  SET @sql_str = N‘

  SELECT * FROM (

  SELECT [‘[email protected]+‘],[‘[email protected]+‘],[‘[email protected]+‘] FROM [‘[email protected]+‘]‘[email protected]_where+‘) p PIVOT

  (SUM([‘[email protected]+‘]) FOR [‘[email protected]+‘] IN ( ‘+ @sql_col +‘) ) AS pvt

  ORDER BY pvt.[‘[email protected]+‘]‘

  --PRINT (@sql_str)

  EXEC (@sql_str)

时间: 2024-10-12 12:05:35

SQL Server 动态行转列(轉載)的相关文章

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

一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 方法一:使用拼接SQL,静态列字段: 方法二:使用拼接SQL,动态列字段: 方法三:使用PIVOT关系运算符,静态列字段: 方法四:使用PIVOT关系运算符,动态列字段: 扩展阅读一:参数化表名.分组列.行转列字段.字段值: 扩展阅读二:在前面的基础上加入条件过滤: 参考文献(References) 二.背景(Contexts) 其实行转列并不是一个什么新鲜的

SQL server 动态行转列

在学习数据库的时候,遇到了怎么把数据表中的内容转变成数据表的字段,在此,记录一下自己对行转列的理解 比如有个学生成绩表: stuid:学号 course:科目 score:成绩 表的内容为: stuid course score 0101 语文     78 0101 数学     90 0101 英语     67 0101 物理     88 而我们想要的是类似下表: stuid 语文 数学 英语 物理 0101  78 90 67  88 这个时候就需要用到行转列,行转列有动态与静态之分:

代码实现SQL Server动态行转列,不用存储过程

分两步查询,第一步查询出动态列,第二步使用PIVOT函数. 代码: List<DataTable> dataTableList = new List<DataTable>(); #region 指标 DataTable dtEvaItemTitle = db.RunTable<Edu_EvaluationRecord>(string.Format(@" select distinct eva.id, eva.name from Edu_EvaluationRe

转:SQL Server 动态行转列

http://www.cnblogs.com/gaizai/p/3753296.html http://www.cnblogs.com/maanshancss/archive/2013/03/13/2957108.html

SQL SERVER特殊行转列案列一则

原文:SQL SERVER特殊行转列案列一则 今天有个同事找我,他说他有个需求,需要进行行转列,但是又跟一般的行转列有些区别,具体需求如下所说,需要将表1的数据转换为表2的显示格式. 我想了一下,给出了一个解决方法,具体如下所示(先给出测试数据) INSERT INTO TEST SELECT 1,    1,    '定型名称',    '预定型'           UNION ALL SELECT 1,    2,    '进布方式',    '调平'             UNION 

通过sql实现动态行转列

上一章我们讲了固定行转列,本章我们就将一下怎么动态实现行转列的.因为有时候需要行专列的值有成千上万条,不可能再用固定行转列的方法,否则你一定会崩溃掉的.好了,废话不多说,开始吧!常见一张表tmp_test,内容如下: 实现代码:create or replace procedure p_test isv_sql varchar2(2000); cursor cursor_1 isselect distinct subject from tmp_test order by subject; beg

SQL SERVER PIVOT 行转列、列传行

在数据库操作中,有些时候我们遇到需要实现"行转列"的需求,例如一下的表为某店铺的一周收入情况表: WEEK_INCOME(WEEK VARCHAR(10),INCOME DECIMAL) 我们先插入一些模拟数据: INSERT INTO WEEK_INCOME SELECT '星期一',1000 UNION ALL SELECT '星期二',2000 UNION ALL SELECT '星期三',3000 UNION ALL SELECT '星期四',4000 UNION ALL SE

sql server 2012 行转列

table_source PIVOT( 聚合函数(value_column) FOR pivot_column IN(<column_list>) ) 对于一个字段的汇总和转置,只用一次. ) tb pivot(max(copies) for ORDER_TYPE in ([11],[12],[13],[14])) tb 对于多个字段的汇总和转置,要嵌套多次. ) tb pivot(max(copies) for ORDER_TYPE in ([11],[12],[13],[14])) tb

动态行转列 pivot实现

declare @sql varchar(8000)    begin              set @sql=''  --初始化变量@sql              select  @[email protected]+',['+ convert(varchar(10),CreateDate,120)+']' from  vwStationYield               where CreateDate > DATEADD(dd,-14,convert(varchar(10),g