SQL Server中行列转换 Pivot UnPivot
sqlserver行转列函数

sqlserver行转列函数SQL Server中有多种方法可以将行转列,包括使用PIVOT函数、CASE语句和动态SQL等。
在接下来的讨论中,我将介绍这些方法,并提供示例来帮助您理解。
1.使用PIVOT函数:PIVOT函数是SQL Server中实现行转列功能的内置函数。
它将一个由行组成的结果集转换为具有动态列的结果集。
以下是使用PIVOT函数将行转列的示例:```sqlSELECT*FROMSELECT employee_id, department, salaryFROM employeesAS srPIVOTSUM(salary)FOR department IN ([IT], [Finance], [HR])AS piv```在上面的示例中,我们选择员工ID、部门和薪水,并使用PIVOT函数将部门作为列转换。
每个部门的薪水总和将作为新的列显示。
2.使用CASE语句:CASE语句是一种常见的在SQL中实现行转列的方法。
通过使用CASE 语句,我们可以将满足特定条件的行值转换为动态列。
以下是使用CASE语句进行行转列的示例:```sqlSELECT employee_id,MAX(CASE WHEN department = 'IT' THEN salary END) AS IT,MAX(CASE WHEN department = 'Finance' THEN salary END) AS Finance,MAX(CASE WHEN department = 'HR' THEN salary END) AS HRFROM employeesGROUP BY employee_id;```在上面的示例中,我们首先通过GROUPBY将结果按照员工进行分组,然后使用CASE语句将不同部门的薪水作为新的列。
3.使用动态SQL:动态SQL是一种使用SQL Server中的字符串操作来构建和执行动态查询的方法。
SQL Server 动态行转列(参数化表名、分组列、行转列字段、字段值)

一.本文所涉及的内容(Contents)本文所涉及的内容(Contents)背景(Contexts)实现代码(SQL Codes)方法一:使用拼接SQL,静态列字段;方法二:使用拼接SQL,动态列字段;方法三:使用PIVOT关系运算符,静态列字段;方法四:使用PIVOT关系运算符,动态列字段;扩展阅读一:参数化表名、分组列、行转列字段、字段值;扩展阅读二:在前面的基础上加入条件过滤;二.背景(Contexts)其实行转列并不是一个什么新鲜的话题了,甚至已经被大家说到烂了,网上的很多例子多多少少都有些问题,所以我希望能让大家快速的看到执行的效果,所以在动态列的基础上再把表、分组字段、行转列字段、值这四个行转列固定需要的值变成真正意义的参数化,大家只需要根据自己的环境,设置参数值,马上就能看到效果了。
行转列的效果图如图1所示:(图1:行转列效果图)(一) 首先我们先创建一个测试表,往里面插入测试数据,返回表记录如图2所示:--创建测试表IF EXISTS (SELECT*FROM sys.objects WHERE object_id=OBJECT_ID(N'[dbo].[TestRows2Columns]') AND type in (N'U'))DROP TABLE[dbo].[TestRows2Columns]GOCREATE 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'语文',60UNION ALLSELECT N'李四',N'数学',70UNION ALLSELECT N'王五',N'英语',80UNION ALLSELECT N'王五',N'数学',75UNION ALLSELECT N'王五',N'语文',57UNION ALLSELECT N'李四',N'语文',80UNION ALLSELECT N'张三',N'英语',100GOSELECT*FROM[TestRows2Columns](图2:样本数据)(二) 先以静态的方式实现行转列,效果如图3所示:--1:静态拼接行转列SELECT[UserName],SUM(CASE[Subject]WHEN'数学'THEN[Source]ELSE0END) AS'[数学]',SUM(CASE[Subject]WHEN'英语'THEN[Source]ELSE0END) AS'[英语]',SUM(CASE[Subject]WHEN'语文'THEN[Source]ELSE0END) 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 aSELECT@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 pvtORDER 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 pvtORDER BY pvt.[UserName]'PRINT (@sql_str)EXEC (@sql_str)(六) 也许很多人到了上面一步就够了,但是你会发现,当别人拿到你的代码,需要不断的修改成他自己环境中表名、分组列、行转列字段、字段值这几个参数,逻辑如图5所示,所以,我继续对上面的脚本进行修改,你只要设置自己的参数就可以实现行转列了,效果如图4所示:--5:参数化动态PIVOT行转列-- =============================================-- Author: <听风吹雨>-- Create date: <2014.05.26>-- Description: <参数化动态PIVOT行转列>-- Blog: <:///gaizai/>-- =============================================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(['+@row2column+'])FROM ['+@tableName+'] GROUP BY ['+@row2column+']'--PRINT @sql_strEXEC sp_executesql @sql_str,N'@sql_col_out NVARCHAR(MAX) OUTPUT',@sql_col_out=@sql_col OUTPUT --PRINT @sql_colSET@sql_str= N'SELECT * FROM (SELECT ['+@groupColumn+'],['+@row2column+'],['+@row2columnValue+'] FROM ['+@tableName+']) p PIVOT(SUM(['+@row2columnValue+']) FOR ['+@row2column+'] IN ( '+@sql_col+') ) AS pvt ORDER BY pvt.['+@groupColumn+']'--PRINT (@sql_str)EXEC (@sql_str)(图5)(七) 在实际的运用中,我经常遇到需要对基础表的数据进行筛选后再进行行转列,那么下面的脚本将满足你这个需求,效果如图6所示:--6:带条件查询的参数化动态PIVOT行转列-- =============================================-- Author: <听风吹雨>-- Create date: <2014.05.26>-- Description: <参数化动态PIVOT行转列,带条件查询的参数化动态PIVOT行转列>-- Blog: <:///gaizai/>-- =============================================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(['+@row2column+'])FROM ['+@tableName+'] '+@sql_where+' GROUP BY ['+@row2column+']'--PRINT @sql_strEXEC sp_executesql @sql_str,N'@sql_col_out NVARCHAR(MAX) OUTPUT',@sql_col_out=@sql_col OUTPUT --PRINT @sql_colSET@sql_str= N'SELECT * FROM (SELECT ['+@groupColumn+'],['+@row2column+'],['+@row2columnValue+'] FROM['+@tableName+']'+@sql_where+') p PIVOT(SUM(['+@row2columnValue+']) FOR ['+@row2column+'] IN ( '+@sql_col+') ) AS pvt ORDER BY pvt.['+@groupColumn+']'--PRINT (@sql_str)EXEC (@sql_str)(图6)。
SQL Server 2005 PIVOT运算符的使用(一列多行数据合并为一行)

SQL Server 2005 PIVOT运算符的使用PIVOT,UNPIVOT运算符是SQL Server 2005支持的新功能之一,主要用来实现行到列的转换。
本文主要介绍PIVOT运算符的操作,以及如何实现动态PIVOT的行列转换。
关于UNPIVOT及SQL Server 2000下的行列转换请参照本人的其它文章。
一、使用PIVOT和UNPIVOT命令的SQL Server版本要求1、数据库的最低版本要求为SQL Server 2005 或更高。
2、必须将数据库的兼容级别设置为90 或更高。
3、查看我的数据库版本及兼容级别。
如果不知道怎么看数据库版本或兼容级别的话可以在SQL Server Management St udio新建一个查询窗口输入:print @@version,运行之后在我的本机上得到:Microsoft SQL Server 2008 R2 (RTM) - 10.50.1617.0 (X64)Apr 22 2011 19:23:43Copyright (c) Microsoft CorporationData Center Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: S ervice Pack 1)我们选择一个数据库,然后【右键】--【属性】,选择【选项】得到下图的信息。
在确认数据库的版本和兼容级别符合1、2点的要求后,才可以接着继续往下学习。
二、PIVOT的语法SELECT[non-pivoted column],-- optional[additional non-pivoted columns],-- optional[first pivoted column],[additional pivoted columns]FROM(SELECT query producing sql data for pivot-- select pivot columns as dimensions and-- value columns as measures from sql tables)AS TableAliasPIVOT(<aggregation function>(column for aggregation or measure column)-- MIN,MAX,SUM,etcFOR[]IN([first pivoted column],...,[last pivoted column]))AS PivotT ableAliasORDER BY clause–optional三、PIVOT的使用例子1、静态PIVOT的用法为演示,从NorthWind数据库中提取一些记录生成新的Orders表,然后使用PIVO T将行转换到列。
SQLServer行列相互转换命令:PIVOT和UNPIVOT使用详解

SQLServer⾏列相互转换命令:PIVOT和UNPIVOT使⽤详解⼀、版本要求1.数据库的最低版本要求为SQL Server 2005 或更⾼。
2.必须将数据库的兼容级别设置为90 或更⾼。
3.查看我的数据库版本及兼容级别。
如果不知道怎么看数据库版本或兼容级别的话可以在SQL Server Management Studio新建⼀个查询窗⼝输⼊:print @@version,运⾏之后在我的本机上得到:Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (Intel X86)Apr 2 2010 15:53:02Copyright (c) Microsoft CorporationExpress Edition with Advanced Services on Windows NT 5.2 <X86> (Build 3790: Service Pack 2)然后我们选择⼀个数据库然后右键-属性选择[选项]得到下图的信息。
在确认数据库的版本和兼容级别符合1,2点的要求后你才可以接着继续往下学习。
⼆、PIVOT 实现⾏转列1.在这⾥我们先构建⼀个测试数据表(这⾥使⽤的是临时表,以⽅便我们在退出会话的时候⾃动删除表及其数据)⾸先我们先设计⼀个表架构为#Student { 学⽣编号[PK], 姓名, 性别, 所属班级 }的表,然后编写如下T-SQL--创建临时表(仅演⽰,表结构的不合理还请包涵)CREATE TABLE #Student ([学⽣编号]INT IDENTITY(1, 1) PRIMARY KEY, [姓名]NVARCHAR(20), [性别]NVARCHAR(1), [所属班级]NVARCHAR(20))--给临时表插⼊数据INSERT INTO #Student ([姓名], [性别], [所属班级])SELECT'李妹妹', '⼥', '初⼀ 1班'UNION ALLSELECT'泰强', '男', '初⼀ 1班'UNION ALLSELECT'泰映', '男', '初⼀ 1班'UNION ALLSELECT'何谢', '男', '初⼀ 1班'UNION ALLSELECT'李春', '男', '初⼆ 1班'UNION ALLSELECT'吴歌', '男', '初⼆ 1班'UNION ALLSELECT'林纯', '男', '初⼆ 1班'UNION ALLSELECT'徐叶', '⼥', '初⼆ 1班'UNION ALLSELECT'龙门', '男', '初三 1班'UNION ALLSELECT'⼩红', '⼥', '初三 1班'UNION ALLSELECT'⼩李', '男', '初三 1班'UNION ALLSELECT'⼩黄', '⼥', '初三 2班'UNION ALLSELECT'旺财', '男', '初三 2班'UNION ALLSELECT'强强', '男', '初⼆ 1班';以下是查询的结果:2.查询各班级的总⼈数SELECT[所属班级]AS[班级], COUNT(1) AS[⼈数]FROM #Student GROUP BY[所属班级]ORDER BY[⼈数]DESC班级⼈数-------- -----------初⼆ 1班5初⼀ 1班4初三 1班3初三 2班2好了,在这⾥我希望把上⾯的表{ 班级, ⼈数 } 由班级[⾏] 的显⽰转换为班级[列] 的显⽰格式!在此你会看到第⼀个PIVOT⽰例。
SQL优化之——行转列,列转行

SQL优化之——⾏转列,列转⾏⾏转列,列转⾏是我们在开发过程中经常碰到的问题。
⾏转列⼀般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER 2005 新增的运算符PIVOT来实现。
⽤传统的⽅法,⽐较好理解。
层次清晰,⽽且⽐较习惯。
但是PIVOT 、UNPIVOT提供的语法⽐⼀系列复杂的SELECT...CASE 语句中所指定的语法更简单、更具可读性。
下⾯我们通过⼏个简单的例⼦来介绍⼀下列转⾏、⾏转列问题。
我们⾸先先通过⼀个⽼⽣常谈的例⼦,学⽣成绩表(下⾯简化了些)来形象了解下⾏转列CREATE TABLE [StudentScores]([UserName] NVARCHAR(20), --学⽣姓名[Subject] NVARCHAR(30), --科⽬[Score] FLOAT, --成绩)INSERT INTO [StudentScores] SELECT 'Nick', '语⽂', 80INSERT INTO [StudentScores] SELECT 'Nick', '数学', 90INSERT INTO [StudentScores] SELECT 'Nick', '英语', 70INSERT INTO [StudentScores] SELECT 'Nick', '⽣物', 85INSERT INTO [StudentScores] SELECT 'Kent', '语⽂', 80INSERT INTO [StudentScores] SELECT 'Kent', '数学', 90INSERT INTO [StudentScores] SELECT 'Kent', '英语', 70INSERT INTO [StudentScores] SELECT 'Kent', '⽣物', 85如果我想知道每位学⽣的每科成绩,⽽且每个学⽣的全部成绩排成⼀⾏,这样⽅便我查看、统计,导出数据SELECTUserName,MAX(CASE Subject WHEN '语⽂' THEN Score ELSE 0 END) AS '语⽂',MAX(CASE Subject WHEN '数学' THEN Score ELSE 0 END) AS '数学',MAX(CASE Subject WHEN '英语' THEN Score ELSE 0 END) AS '英语',MAX(CASE Subject WHEN '⽣物' THEN Score ELSE 0 END) AS '⽣物'FROM dbo.[StudentScores]GROUP BY UserName查询结果如图所⽰,这样我们就能很清楚的了解每位学⽣所有的成绩了接下来我们来看看第⼆个⼩列⼦。
【TeradataSQL】行列转换函数PIVOT和UNPIVOT、TD_UNPIVOT

【TeradataSQL】⾏列转换函数PIVOT和UNPIVOT、TD_UNPIVOT1.⾏转列函数PIVOTPivot是⽤于将⾏转换为列的关系运算符。
该函数对于报告⽤途很有⽤,因为它允许您聚合和旋转数据以创建易于读取的表。
在SELECT语句的FROM⼦句中指定PIVOT运算符。
对于可以⽤包含透视运算符的select查询指定的其他⼦句没有限制。
(1)语法(2)实例#数据准备CREATE TABLE star1(country VARCHAR(20),state VARCHAR(10), yr INTEGER,qtr VARCHAR(3),sales INTEGER,cogs INTEGER);insert into star1 values('USA','CA',2001,'Q1',30,15);insert into star1 values('Canada','ON',2001,'Q2', 10, 0);insert into star1 values('Canada','BC',2001,'Q3', 10 ,0);insert into star1 values('USA','NY',2001,'Q1',45, 25);insert into star1 values('USA','CA',2001,'Q2', 50 ,20);SELECT*FROM star1;单个转换维度(Quarter)实例,将Q1、Q2、Q3季度的sales和cogs值转换为列,转换效果如下:#写法⼀SELECT*FROM star1 PIVOT (SUM(sales) as ss1, SUM(cogs) as sc FORqtrIN ('Q1'ASQuarter1,'Q2'AS Quarter2,'Q3'AS Quarter3))Tmp;#写法⼆SELECT country, state,SUM(case when yr =2001and qtr ='Q1'then sales end) as "2001_q1_ss",SUM(case when yr =2001and qtr ='Q2'then sales end) as "2001_ q2_ ss",SUM(case when yr =2001and qtr ='Q3'then sales end) as "2001_q3_ss",SUM(case when yr =2001and qtr ='Q1'then cogs end) as "2001_ q1_sc",SUM(case when yr =2001and qtr ='Q2'then cogs end) as "2001_q2_sc",SUM(case when yr =2001and qtr ='Q3'then cogs end) as "2001_q3_sc"FROM star1GROUP BY country, state;两个转换维度(year、Quarter)实例,将2001年Q1、Q2、Q3季度的sales和cogs值转换为列,转换效果如下:#写法⼀(默认按照聚合字段sales、cogs和 FOR列表字段yr、qtr以外的表中字段进⾏分组,本例中按照country、state字段分组)SELECT*FROM star1 PIVOT (SUM(sales) AS ss1, SUM(cogs) AS sc FOR(yr, qtr)IN ((2001, 'Q1'),(2001, 'Q2'),(2001, 'Q3')))Tmp;#写法⼆SELECT country, state,SUM(case when yr =2001and qtr ='Q1'then sales end) as "2001_q1_ss",SUM(case when yr =2001and qtr ='Q2'then sales end) as "2001_ q2_ ss",SUM(case when yr =2001and qtr ='Q3'then sales end) as "2001_q3_ss",SUM(case when yr =2001and qtr ='Q1'then cogs end) as "2001_ q1_sc",SUM(case when yr =2001and qtr ='Q2'then cogs end) as "2001_q2_sc",SUM(case when yr =2001and qtr ='Q3'then cogs end) as "2001_q3_sc"FROM star1GROUP BY country, state;先⾏转列,后列转⾏CREATE TABLE t1 (place CHAR(5), sales1 INTEGER, sales2 INTEGER,sales3 INTEGER, sales4 INTEGER, sales5 INTEGER)PRIMARY INDEX ( place );insert into t1 values('Hyd' ,110 ,100 ,1000 ,1100, 500);insert into t1 values('Che', 120 ,200, 2000, 1200, 600);insert into t1 values('Kol' ,150 ,500, 5000, 1500, 900 );insert into t1 values('Mee', 140, 400, 4000 ,1400 ,800);insert into t1 values('Pun', 130 ,300, 3000 ,1300, 700);SELECT*from (SELECT*from t1UNPIVOT(salevalfor sales in (sales1, sales2, sales3,sales4, sales5))dt1)dt2PIVOT(SUM(saleval)for place in ('hyd','Che','pun','mee','kol'))dt3;2.列转⾏函数UNPIVOTUNPIVOT是透视操作的反向操作。
sql server行转列查询语句

sql server行转列查询语句SQL Server行转列查询语句是一种非常有用的查询技巧,可以将一行的数据转换为多列的形式,这对于某些业务场景非常实用。
本文将详细介绍SQL Server行转列查询语句的使用方法和注意事项,希望能帮助读者更好地掌握这一技巧。
一、什么是行转列查询语句行转列查询语句是一种将一行数据转换为多列数据的查询技巧。
在数据库中,数据通常以行的形式存储,每一行代表一个记录。
但是在某些场景下,我们需要将行数据转换为列数据,以便更好地展示和处理数据。
SQL Server提供了一些函数和关键字来实现行转列查询。
二、行转列查询的应用场景行转列查询常见的应用场景包括以下几种:1. 交叉表查询:将某一列的值作为新列,将另一列的值作为新行,用于统计和分析数据。
2. 报表生成:将多行数据按照某个字段进行分组,转换为多列数据,方便生成报表。
3. 数据展示:将一张表中的多行数据转换为一行数据,用于展示和查询。
三、行转列查询的基本语法SQL Server中实现行转列查询通常使用PIVOT和UNPIVOT关键字。
下面是行转列查询的基本语法:1. PIVOT语法:SELECT [列1], [列2], ...FROM [表名]PIVOT(聚合函数([列名])FOR [列名] IN ([列值1], [列值2], ...)) AS [别名]2. UNPIVOT语法:SELECT [列名], [值]FROM [表名]UNPIVOT([值] FOR [列名] IN ([列1], [列2], ...)) AS [别名]需要注意的是,PIVOT语句中的聚合函数可以是SUM、COUNT、AVG 等,适用于需要对数据进行统计的场景。
四、行转列查询的实际案例为了更好地理解行转列查询,下面以一个实际案例来演示如何使用行转列查询语句。
我们有一个销售数据表sales_data,包含以下列:产品名称(product_name)、区域(region)、销售额(sales_amount)。
SqlServerPIVOT函数快速实现行转列,UNPIVOT实现列转行(转)

SqlServerPIVOT函数快速实现⾏转列,UNPIVOT实现列转⾏(转)我们在写Sql语句的时候没经常会遇到将查询结果⾏转列,列转⾏的需求,拼接sql字符串,然后使⽤sp_executesql执⾏sql字符串是⽐较常规的⼀种做法。
但是这样做实现起来⾮常复杂,⽽在SqlServer2005中我们有了PIVOT/UNPIVOT函数可以快速实现⾏转列和列转⾏的操作。
PIVOT函数,⾏转列PIVOT函数的格式如下PIVOT(<聚合函数>([聚合列值]) FOR [⾏转列前的列名] IN([⾏转列后的列名1],[⾏转列后的列名2],[⾏转列后的列名3],.......[⾏转列后的列名N])) <聚合函数>就是我们使⽤的SUM,COUNT,AVG等Sql聚合函数,也就是⾏转列后计算列的聚合⽅式。
[聚合列值]要进⾏聚合的列名[⾏转列前的列名]这个就是需要将⾏转换为列的列名。
[⾏转列后的列名]这⾥需要声明将⾏的值转换为列后的列名,因为转换后的列名其实就是转换前⾏的值,所以上⾯格式中的[⾏转列后的列名1],[⾏转列后的列名2],[⾏转列后的列名3],......[⾏转列后的列名N]其实就是[⾏转列前的列名]每⼀⾏的值。
下⾯我们来看⼀个例⼦有⼀张表名为[ShoppingCart]有三列[Week],[TotalPrice],[GroupId],数据和表结构如下所⽰:CREATE TABLE [dbo].[ShoppingCart]([Week] [int] NOT NULL,[TotalPrice] [decimal](18, 0) NOT NULL,[GroupId] [int] NULL) ON [PRIMARY]GOALTER TABLE [dbo].[ShoppingCart] ADD DEFAULT ((0)) FOR [TotalPrice]GOINSERT [dbo].[ShoppingCart] ([Week], [TotalPrice], [GroupId]) VALUES (1, CAST(10 AS Decimal(18, 0)), 1)GOINSERT [dbo].[ShoppingCart] ([Week], [TotalPrice], [GroupId]) VALUES (2, CAST(20 AS Decimal(18, 0)), 1)GOINSERT [dbo].[ShoppingCart] ([Week], [TotalPrice], [GroupId]) VALUES (3, CAST(30 AS Decimal(18, 0)), 1)GOINSERT [dbo].[ShoppingCart] ([Week], [TotalPrice], [GroupId]) VALUES (4, CAST(40 AS Decimal(18, 0)), 1)GOINSERT [dbo].[ShoppingCart] ([Week], [TotalPrice], [GroupId]) VALUES (5, CAST(50 AS Decimal(18, 0)), 1)GOINSERT [dbo].[ShoppingCart] ([Week], [TotalPrice], [GroupId]) VALUES (6, CAST(60 AS Decimal(18, 0)), 1)GOINSERT [dbo].[ShoppingCart] ([Week], [TotalPrice], [GroupId]) VALUES (7, CAST(70 AS Decimal(18, 0)), 1)GO现在我们是⽤PIVOT函数将列[WEEK]的⾏值转换为列,并使⽤聚合函数Count(TotalPrice)来统计每⼀个Week列在转换前有多少⾏数据,语句如下所⽰:select *from ShoppingCart as CPIVOT(count(TotalPrice) FOR [Week] IN([1],[2],[3],[4],[5],[6],[7])) AS T查询结果如下:我们可以看到PIVOT函数成功地将[ShoppingCart]表列[Week]的⾏值转换为了七列,并且每⼀列统计转换前的⾏数为1,这符合我们的预期结果。
sqlserver行转列函数

sqlserver行转列函数
sqlserver行转列函数
SQL Server行转列函数
SQL Server行转列函数是SQL Server中常用的数据处理功能,它可以将行转换为列,从而实现数据的转换和操作。
SQL Server行转列函数有两种:PIVOT函数和UNPIVOT函数。
PIVOT函数是将行转换为列的函数,它可以将一行的数据转换为多行的数据,从而转换为列。
例如,如果有一个表,其中有一列存储多个值,可以使用PIVOT函数将其转换为多列,每列存储不同值。
UNPIVOT函数是将列转换为行的函数,它可以将多列的数据转换为一行的数据,从而转换为行。
例如,如果有一个表,其中有多列存储不同的值,可以使用UNPIVOT函数将其转换为一行的数据,每行存储不同的值。
SQL Server中的行转列函数主要用于数据统计、报表生成、数据分析等应用中。
它可以帮助用户快速实现数据的转换和操作,从而为用户节省大量的时间和精力,提高工作效率。
总之,SQL Server行转列函数是SQL Server中常用的数据处理功能,它可以帮助用户实现数据的转换和操作,从而提高工作效率,帮助用户提升工作效率。
SQLSERVER中PIVOT和UNPIVOT的用法【分组统计】

SQLSERVER中PIVOT和UNPIVOT的⽤法【分组统计】USE LocalAppDBGO---Use aggregate functionSELECT C.customerid, city,CASEWHEN COUNT(orderid) = 0 THEN 'no_orders'WHEN COUNT(orderid) <= 2 THEN 'upto_two_orders'WHEN COUNT(orderid) > 2 THEN 'more_than_two_orders'END AS categoryFROM dbo.Customers AS C LEFT OUTER JOIN dbo.Orders AS O ON C.customerid = O.customeridGROUP BY C.customerid, city;---use pivot key word: Find city [no_orders]/[upto_two_orders]/[more_than_two_orders]'s CustomerID CountSELECT city,[no_orders],[upto_two_orders],[more_than_two_orders]FROM(SELECT C.[customerid], [city],(CASE WHEN COUNT(orderid) = 0 THEN 'no_orders'WHEN COUNT(orderid) <= 2 THEN 'upto_two_orders'WHEN COUNT(orderid) > 2 THEN 'more_than_two_orders'END) AS [category]FROM dbo.Customers AS C LEFT OUTER JOIN dbo.Orders AS O ON C.customerid = O.customeridGROUP BY C.customerid, city) pPIVOT(count(p.[customerid]) FOR p.categoryIN ([no_orders],[upto_two_orders],[more_than_two_orders])) AS pvt---Can Use this SQL Statement To Replace PIVOT(Just Can Use After SQL 2005 Version ) Key WordSELECT city,COUNT(CASE WHEN category = 'no_orders'THEN customerid END) AS [no_orders],COUNT(CASE WHEN category = 'upto_two_orders'THEN customerid END) AS [upto_two_orders],COUNT(CASE WHEN category = 'more_than_two_orders'THEN customerid END) AS [more_than_two_orders]FROM (SELECT C.customerid, city,CASEWHEN COUNT(orderid) = 0 THEN 'no_orders'WHEN COUNT(orderid) <= 2 THEN 'upto_two_orders'WHEN COUNT(orderid) > 2 THEN 'more_than_two_orders'END AS categoryFROM dbo.Customers AS CLEFT OUTER JOIN dbo.Orders AS OON C.customerid = O.customeridGROUP BY C.customerid, city) AS DGROUP BY city;---Now Test the UNPIVOT Key WordSELECT city,[no_orders],[upto_two_orders],[more_than_two_orders] INTO dbo.PivotedCategoriesFROM(SELECT C.[customerid], [city],(CASE WHEN COUNT(orderid) = 0 THEN 'no_orders'WHEN COUNT(orderid) <= 2 THEN 'upto_two_orders'WHEN COUNT(orderid) > 2 THEN 'more_than_two_orders'END) AS [category]FROM dbo.Customers AS C LEFT OUTER JOIN dbo.Orders AS O ON C.customerid = O.customeridGROUP BY C.customerid, city) pPIVOT(count(p.[customerid]) FOR p.categoryIN ([no_orders],[upto_two_orders],[more_than_two_orders])) AS pvt---UPDATE dbo.PivotedCategoriesSET no_orders = NULL, upto_two_orders = 3WHERE city = 'Madrid';SELECT * FROM PivotedCategories---SELECT city, category, num_custsFROM dbo.PivotedCategoriesUNPIVOT( num_custs FORcategory IN([no_orders],[upto_two_orders],[more_than_two_orders])) AS UNPvt---Drop the Test TableDROP TABLE dbo.PivotedCategories;---This Dome Test OVER Key WordSELECT orderid, customerid,COUNT(*) OVER(PARTITION BY customerid) AS num_ordersFROM dbo.OrdersWHERE customerid IS NOT NULLAND orderid % 2 = 1;---Use Aggregate FunctionSELECT orderid, customerid,COUNT(*) AS num_ordersFROM dbo.OrdersWHERE customerid IS NOT NULLAND orderid % 2 = 1GROUP BY orderid, customerid----SELECT seqno,username,ROW_NUMBER() OVER(ORDER BY seqno DESC) AS [Sseqno],password,enabledFROM dbo.aduserORDER BY seqno----SELECT seqno,username,ROW_NUMBER() OVER(PARTITION BY username ORDER BY seqno DESC) AS [Sseqno],password,enabled FROM dbo.aduserORDER BY seqno--SELECT seqno,username,COUNT(*) OVER(PARTITION BY username) AS [CT],password,enabledFROM dbo.aduserORDER BY seqno---SELECT customerid FROM dbo.CustomersEXCEPTSELECT customerid FROM dbo.Orders;---SELECT customerid FROM dbo.CustomersUNIONSELECT customerid FROM dbo.Orders; 很悲催,之前写的SQL 相关⽂档⼈间蒸发鸟,⼜得慢慢积累,囧~ 。
SqlServer行转列(PIVOT),列转行(UNPIVOT)总结

SqlServer⾏转列(PIVOT),列转⾏(UNPIVOT)总结PIVOT⽤于将列值旋转为列名(即⾏转列)语法:table_sourcePIVOT(聚合函数(value_column)FOR pivot_columnIN(<column_list>))UNPIVOT⽤于将列明转为列值(即列转⾏)语法:table_sourceUNPIVOT(value_columnFOR pivot_columnIN(<column_list>))注意:PIVOT、UNPIVOT是SQL Server 2005的语法,使⽤需修改数据库兼容级别在数据库属性->选项->兼容级别改为 90⼀、⾏转列1、建⽴表格ifobject_id('tb')isnotnulldroptabletbgoCreate 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)goSelect * from tb2、使⽤SQL Server 2000静态SQLselect姓名,Max (case课程when'语⽂'then分数else 0 end)语⽂,Max (case课程when'数学'then分数else 0 end)数学,Max (case课程when'物理'then分数else 0 end)物理From tbGroup by姓名3、使⽤SQL Server 2000动态SQLdeclare@sqlvarchar(500)set@sql='select姓名'select@sql=@sql+',max(case课程when '''+课程+''' then分数else 0 end)['+课程+']'from(selectdistinct课程fromtb)a--同from tb group by课程,默认按课程名排序set@sql=@sql+' from tb group by姓名'exec(@sql)--使⽤isnull(),变量先确定动态部分declare@sqlvarchar(8000)select@sql=isnull(@sql+',','')+' max(case课程when '''+课程+''' then分数else 0 end) ['+课程+']'from(selectdistinct课程fromtb)asaset@sql='select姓名,'+@sql+' from tb group by姓名'exec(@sql)4、使⽤SQL Server 2005静态SQLselect*fromtb pivot(max(分数)for课程in(语⽂,数学,物理))a5、使⽤SQL Server 2005动态SQL--使⽤stuff()declare@sqlvarchar(8000)set@sql='' --初始化变量@sqlselect@sql=@sql+','+课程fromtbgroupby课程--变量多值赋值set@sql=stuff(@sql,1,1,'')--去掉⾸个','set@sql='select * from tb pivot (max(分数) for课程in ('+@sql+'))a'exec(@sql)--或使⽤isnull()declare@sqlvarchar(8000)–-获得课程集合select@sql=isnull(@sql+',','')+课程fromtbgroupby课程set@sql='select * from tb pivot (max(分数) for课程in ('+@sql+'))a'exec(@sql)⼆、⾏转列结果加上总分、平均分1、使⽤SQL Server 2000静态SQLselect姓名,max(case课程when'语⽂'then分数else0end)语⽂,max(case课程when'数学'then分数else0end)数学,max(case课程when'物理'then分数else0end)物理,sum(分数)总分,cast(avg(分数*1.0)asdecimal(18,2))平均分fromtbgroupby姓名2、使⽤SQL Server 2000动态SQL--SQL SERVER 2000动态SQLdeclare@sqlvarchar(500)set@sql='select姓名'select@sql=@sql+',max(case课程when '''+课程+''' then分数else 0 end)['+课程+']'from(selectdistinct课程fromtb)aset@sql=@sql+',sum(分数)总分,cast(avg(分数*1.0) as decimal(18,2)) 平均分from tb group by姓名' exec(@sql)3、使⽤SQL Server 2005静态SQLselectm.*,n.总分,n.平均分from(select*fromtb pivot(max(分数)for课程in(语⽂,数学,物理))a)m,(select姓名,sum(分数)总分,cast(avg(分数*1.0)asdecimal(18,2))平均分fromtbgroupby姓名)nwherem.姓名=n.姓名4、使⽤SQL Server 2005动态SQLdeclare@sqlvarchar(8000)set@sql='' --初始化变量@sqlselect@sql=@sql+','+课程fromtbgroupby课程--变量多值赋值--同select @sql = @sql + ','+课程from (select distinct课程from tb)aset@sql=stuff(@sql,1,1,'')--去掉⾸个','set@sql='select m.* , n.总分,n.平均分from(select * from (select * from tb) a pivot (max(分数) for课程in ('+@sql+')) b) m ,(select姓名,sum(分数)总分, cast(avg(分数*1.0) as decimal(18,2))平均分from tb group by姓名) n where m.姓名= n.姓名'exec(@sql)--或使⽤isnull()declare@sqlvarchar(8000)select@sql=isnull(@sql+',','')+课程fromtbgroupby课程set@sql='select m.* , n.总分,n.平均分from(select * from (select * from tb) a pivot (max(分数) for课程in ('+@sql+')) b) m ,(select姓名,sum(分数)总分, cast(avg(分数*1.0) as decimal(18,2))平均分from tb group by姓名) n where m.姓名= n.姓名'exec(@sql)⼆、列转⾏1、建⽴表格ifobject_id('tb')isnotnulldroptabletbgocreatetabletb(姓名varchar(10),语⽂int,数学int,物理int)insertintotbvalues('张三',74,83,93)insertintotbvalues('李四',74,84,94)goselect*fromtb2、使⽤SQL Server 2000静态SQL--SQL SERVER 2000静态SQL。
SQLServer中Pivot()函数实现动态行转列

SQLServer中Pivot()函数实现动态⾏转列⼀般情况下Pivot()函数中in中只能写死,因为PIVOT()的in中不⽀持⼦查询,所以这样的话只能⽤存储过程来解决;CREATE PROCEDURE InsurancePivot@Foldercode VARCHAR(50),@isY VARCHAR(4)ASBEGIN DECLARE @ColumnNames VARCHAR(3000)SET @ColumnNames=''SELECT @ColumnNames = @ColumnNames + '[' + TESTNO + '],'FROM ( SELECT TESTNO FROM ORDTASKLEFT JOIN TESTS ON TESTS.TESTCODE = ORDTASK.TESTCODEWHERE ORDTASK.FOLDERNO IN (SELECT FOLDERNO FROM FOLDERS WHERE FOLDERCODE = @Foldercode) ) t SET @ColumnNames= LEFT(@ColumnNames, LEN(@ColumnNames)-1)DECLARE @selectSQL NVARCHAR(3000)SET @selectSQL= 'SELECT P.* FROM ( select foldercode as "受理单编号",ordcode as "样品编号",orders.ORIGINALNO as "原始编号", as "姓名", pa.SEX as "性别", pa.AGE as "年龄", pa.ADDRESS as "现住址", folders.DATERECV as "收样⽇期",FINAL,name.TESTCODE, orders.SAMPLINGDATE, TESTNOfrom orders left join folders on orders.folderno = folders.foldernoleft join PATIENTS pa on pa.PID = orders.PIDleft join (select ordno, results.FINAL,tests.testno ,tests.testcodefrom analytesleft join ORDTASK on ordtask.TESTCODE = analytes.TESTCODE and ordtask.METHOD = analytes.METHODleft join results on results.ANALYTE = analytes.ANALYTE and results.ORDTASKNO = ordtask.ORDTASKNOleft join tests on tests.testcode = analytes.TESTCODEwhere analytes.displayflag = '''+@isY+''') name on name.ordno = orders.ordno where foldercode = '''+@Foldercode+''' ) apivot( max(FINAL) for TESTNO in ({0}))p'SET @selectSQL= REPLACE(@selectSQL,'{0}',@ColumnNames)EXEC sp_executesql @selectSQLENDGO。
使用SQLSERVERPIVOT实现行列转置

使⽤SQLSERVERPIVOT实现⾏列转置⼀般我们在使⽤SQL语句实现⾏列转置时候,最常⽤的⽅法⽆外乎就是 case语句来实现,但是如果需要需要转置的列太多,那么case起来语句就⽆限庞⼤,⼗分不⽅便,sql server中的PIVOT就可以帮助我们解决此类问题PIVOT語法,如下:SELECT <non-pivoted column>,[first pivoted column] AS <column name>,[second pivoted column] AS <column name>,...[last pivoted column] AS <column name>FROM(<SELECT query that produces the data>)AS <alias for the source query>PIVOT(<aggregation function>(<column being aggregated>)FOR[<column that contains the values that will become column headers>]IN ( [first pivoted column], [second pivoted column],... [last pivoted column])) AS <alias for the pivot table><optional ORDER BY clause>;PIVOT語法剖析:PIVOT的語法分三層,⽤三個步驟來使⽤。
第⼀步驟:先把要PIVOT的原始資料查詢(Query)好。
第⼆步驟:設定好PIVOT的欄位與⽅式。
第三步驟:依PIVOT好了的資料,呈現結果。
SELECT <non-pivoted column>, ---- 第三步驟在此,呈現PIVOT後的資料。
SQLServer行列互转实现思路(聚合函数)

SQLServer⾏列互转实现思路(聚合函数)有时候会碰到⾏转列的需求(也就是将列的值作为列名称),通常我都是⽤ CASE END + 聚合函数来实现的。
如下:declare @t table(StudentName nvarchar(20),Subject nvarchar(20),Score int)Insert into @t (StudentName,Subject,Score) values ( '学⽣A', '中⽂', 80 );Insert into @t (StudentName,Subject,Score) values ( '学⽣A', '数学', 78 );Insert into @t (StudentName,Subject,Score) values ( '学⽣A', '英语', 92 );Insert into @t (StudentName,Subject,Score) values ( '学⽣B', '中⽂', 89 );Insert into @t (StudentName,Subject,Score) values ( '学⽣B', '数学', 87 );Insert into @t (StudentName,Subject,Score) values ( '学⽣B', '英语', 75 );Insert into @t (StudentName,Subject,Score) values ( '学⽣C', '中⽂', 92 );Insert into @t (StudentName,Subject,Score) values ( '学⽣C', '数学', 74 );Insert into @t (StudentName,Subject,Score) values ( '学⽣C', '英语', 65 );Insert into @t (StudentName,Subject,Score) values ( '学⽣D', '中⽂', 79 );Insert into @t (StudentName,Subject,Score) values ( '学⽣D', '数学', 83 );Insert into @t (StudentName,Subject,Score) values ( '学⽣D', '英语', 81 );Insert into @t (StudentName,Subject,Score) values ( '学⽣E', '中⽂', 73 );Insert into @t (StudentName,Subject,Score) values ( '学⽣E', '数学', 84 );Insert into @t (StudentName,Subject,Score) values ( '学⽣E', '英语', 93 );Insert into @t (StudentName,Subject,Score) values ( '学⽣F', '中⽂', 79 );Insert into @t (StudentName,Subject,Score) values ( '学⽣F', '数学', 86 );Insert into @t (StudentName,Subject,Score) values ( '学⽣F', '英语', 84 );select StudentName,sum(case when Subject = N'中⽂' then Score else 0 end) Chinese,sum(case when Subject = N'数学' then Score else 0 end) Math,sum(case when Subject = N'英语' then Score else 0 end) Engilshfrom @tgroup by StudentName今天看到⼀个新的写法,pivot 可以实现相同的功能(2005才开始⽀持)。
sqlserver纵横表的转换

sqlserver纵横表的转换 在平常的⼯作中或者⾯试中,我们可能有遇到过数据库的纵横表的转换问题。
今天我们就来讨论下。
1.创建表 ⾸先我们来创建⼀张表。
sql语句:1--1. 创建数据表2if OBJECT_ID('Score') is not null drop table Score34create table Score5 (6姓名nvarchar(128),7课程nvarchar(128),8分数int9 )1011insert into Score values('张三','语⽂',98)12insert into Score values('张三','数学',89)13insert into Score values('张三','物理',78)14insert into Score values('李四','语⽂',79)15insert into Score values('李四','数学',88)16insert into Score values('李四','物理',100)1718select*from Score执⾏结果:2. 传统的纵横表转换2.1 纵表转横表先看看我们要转成的横表张什么样⼦:既然这个表只有两列,那么可以根据姓名进⾏分组。
先把姓名拼凑出来,后⾯的分数我们再想办法。
sql:select t.姓名2from Score as t 3group by t.姓名结果:分析:1. 我们先拿到语⽂这个科⽬的分数。
既然我们⽤到了group by 语句,这⾥肯定要⽤聚合函数来求分数。
2. ⽽且我们只需要语⽂这⼀科的成绩,分组出来的⼀共有 3列,分别是语⽂、数学、物理。
SQL Server 动态行转列(参数化表名、分组列、行转列字段、字段值)

一.本文所涉及的内容(Contents)本文所涉及的内容(Contents)背景(Contexts)实现代码(SQL Codes)方法一:使用拼接SQL,静态列字段;方法二:使用拼接SQL,动态列字段;方法三:使用PIVOT关系运算符,静态列字段;方法四:使用PIVOT关系运算符,动态列字段;扩展阅读一:参数化表名、分组列、行转列字段、字段值;扩展阅读二:在前面的基础上加入条件过滤;二.背景(Contexts)其实行转列并不是一个什么新鲜的话题了,甚至已经被大家说到烂了,网上的很多例子多多少少都有些问题,所以我希望能让大家快速的看到执行的效果,所以在动态列的基础上再把表、分组字段、行转列字段、值这四个行转列固定需要的值变成真正意义的参数化,大家只需要根据自己的环境,设置参数值,马上就能看到效果了。
行转列的效果图如图1所示:(图1:行转列效果图)(一) 首先我们先创建一个测试表,往里面插入测试数据,返回表记录如图2所示:--创建测试表IF EXISTS (SELECT*FROM sys.objects WHERE object_id=OBJECT_ID(N'[dbo].[TestRows2Columns]') AND type in (N'U'))DROP TABLE[dbo].[TestRows2Columns]GOCREATE 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'语文',60UNION ALLSELECT N'李四',N'数学',70UNION ALLSELECT N'王五',N'英语',80UNION ALLSELECT N'王五',N'数学',75UNION ALLSELECT N'王五',N'语文',57UNION ALLSELECT N'李四',N'语文',80UNION ALLSELECT N'张三',N'英语',100GOSELECT*FROM[TestRows2Columns](图2:样本数据)(二) 先以静态的方式实现行转列,效果如图3所示:--1:静态拼接行转列SELECT[UserName],SUM(CASE[Subject]WHEN'数学'THEN[Source]ELSE0END) AS'[数学]',SUM(CASE[Subject]WHEN'英语'THEN[Source]ELSE0END) AS'[英语]',SUM(CASE[Subject]WHEN'语文'THEN[Source]ELSE0END) 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 aSELECT@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 pvtORDER 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 pvtORDER BY pvt.[UserName]'PRINT (@sql_str)EXEC (@sql_str)(六) 也许很多人到了上面一步就够了,但是你会发现,当别人拿到你的代码,需要不断的修改成他自己环境中表名、分组列、行转列字段、字段值这几个参数,逻辑如图5所示,所以,我继续对上面的脚本进行修改,你只要设置自己的参数就可以实现行转列了,效果如图4所示:--5:参数化动态PIVOT行转列-- =============================================-- Author: <听风吹雨>-- Create date: <2014.05.26>-- Description: <参数化动态PIVOT行转列>-- Blog: <:///gaizai/>-- =============================================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(['+@row2column+'])FROM ['+@tableName+'] GROUP BY ['+@row2column+']'--PRINT @sql_strEXEC sp_executesql @sql_str,N'@sql_col_out NVARCHAR(MAX) OUTPUT',@sql_col_out=@sql_col OUTPUT --PRINT @sql_colSET@sql_str= N'SELECT * FROM (SELECT ['+@groupColumn+'],['+@row2column+'],['+@row2columnValue+'] FROM ['+@tableName+']) p PIVOT(SUM(['+@row2columnValue+']) FOR ['+@row2column+'] IN ( '+@sql_col+') ) AS pvt ORDER BY pvt.['+@groupColumn+']'--PRINT (@sql_str)EXEC (@sql_str)(图5)(七) 在实际的运用中,我经常遇到需要对基础表的数据进行筛选后再进行行转列,那么下面的脚本将满足你这个需求,效果如图6所示:--6:带条件查询的参数化动态PIVOT行转列-- =============================================-- Author: <听风吹雨>-- Create date: <2014.05.26>-- Description: <参数化动态PIVOT行转列,带条件查询的参数化动态PIVOT行转列>-- Blog: <:///gaizai/>-- =============================================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(['+@row2column+'])FROM ['+@tableName+'] '+@sql_where+' GROUP BY ['+@row2column+']'--PRINT @sql_strEXEC sp_executesql @sql_str,N'@sql_col_out NVARCHAR(MAX) OUTPUT',@sql_col_out=@sql_col OUTPUT --PRINT @sql_colSET@sql_str= N'SELECT * FROM (SELECT ['+@groupColumn+'],['+@row2column+'],['+@row2columnValue+'] FROM['+@tableName+']'+@sql_where+') p PIVOT(SUM(['+@row2columnValue+']) FOR ['+@row2column+'] IN ( '+@sql_col+') ) AS pvt ORDER BY pvt.['+@groupColumn+']'--PRINT (@sql_str)EXEC (@sql_str)(图6)。
sql行列转换Pivotunpivot)

sql行列转换Pivotunpivot)sql 行列转换 Pivot/unpivot)如您所知,关系表是表格化的,即,它们以列-值对的形式出现。
假设一个表名为CUSTOMERS。
SQL> desc customersName Null? Type----------------------------------------- -------- ---------------------------CUST_ID NUMBER(10)CUST_NAME VARCHAR2(20)STATE_CODE VARCHAR2(2)TIMES_PURCHASED NUMBER(3)选定该表:select cust_id, state_code, times_purchasedfrom customersorder by cust_id;输出结果如下:CUST_ID STATE_CODE TIMES_PURCHASED------- ---------- ---------------1 CT 12 NY 103 NJ 24 NY 4...and so on ...注意数据是如何以行值的形式显示的:针对每个客户,该记录显示了客户所在的州以及该客户在商店购物的次数。
当该客户从商店购买更多物品时,列 times_purchased 会进行更新。
现在,假设您希望统计一个报表,以了解各个州的购买频率,即,各个州有多少客户只购物一次、两次、三次等等。
如果使用常规 SQL,您可以执行以下语句:select state_code, times_purchased, count(1) cntfrom customersgroup by state_code, times_purchased;输出如下:ST TIMES_PURCHASED CNT-- --------------- ----------CT 0 90CT 1 165CT 2 179CT 3 173CT 4 173CT 5 152...and so on ...这就是您所要的信息,但是看起来不太方便。
sqlserver列转行函数

sqlserver列转行函数SQLServer中的列转行函数(PIVOT)是一种特殊的函数,它可以将多个列中的数据按行展开,将多行的数据转换为单独的行中的多列。
PIVOT函数的使用可以从多个方面实现数据转换,因此它可以用来查询和汇总多重结果,并将其按列整理出来。
PIVOT实际是一种查询语句,它将一个表中的数据“旋转”,从而可以以更有效的方式显示。
它可以用于将表中的行数据转换为列数据,从而可以更有效地进行报表分析和信息可视化。
PIVOT函数的语法通常由以下几部分组成:SELECT句:用于指定需要被查询的列;FROM句:用于指定在数据源中查询列;PIVOT句:用于指定要列转行的列,以及将查询结果转换为行列值;WHERE句:用于定义查询结果中筛选出的行;ORDER BY句:用于定义查询结果中排序的列。
例如,假设我们有一张名为“Students”的表,用于跟踪学生取得的各科成绩,如下所示:StudentID Subject Score1 Math 971 Science 921 English 882 Math 782 Science 752 English 90我们将使用PIVOT函数将“Subjects”列转换为行,从而可以获得每个学生的成绩,如下所示:StudentID Math Science English1 97 92 882 78 75 90以上是用PIVOT函数将行转换为列的示例,这在报表分析和数据可视化方面非常有用。
类似地,PIVOT函数还可以将列转换为行,用于实现更复杂的数据转换功能。
例如,假设我们有一张表,该表包含每个学生在四个不同领域(语文、数学、物理和化学)中的成绩,如下所示:StudentID Subject Score1 Chinese 971 Math 921 Physics 881 Chemistry 792 Chinese 782 Math 752 Physics 902 Chemistry 87我们可以使用以下PIVOT语句将列转换为行,以此获得每个学生的成绩表:SELECT *FROM(SELECT StudentID, Subject, ScoreFROM Students) AS SourceTablePIVOT(SUM(Score)FOR Subject IN ([Chinese], [Math], [Physics], [Chemistry])) AS PivotTable;以上语句将会返回以下查询结果:StudentID Chinese Math Physics Chemistry1 97 92 88 792 78 75 90 87以上是使用PIVOT函数在SQL Server中将列转换为行的示例。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
)
UNPIVOT用于将列明转为列值(即列转行),在SQL Server 2000可以用UNION来实现
完整语法:
table_source
UNPIVOT(
value_column
FOR pivot_column
IN(<column_list>)
)
李四 74 84 94
张三 74 83 93
3、使用SQL Server 2000动态SQL
--SQL SERVER 2000动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
--变量按sql语言顺序赋值
select@sql=isnull(@sql+',','')+课程fromtbgroupby课程
set@sql='select m.* , n.总分,n.平均分from
(select * from (select * from tb) a pivot (max(分数) for课程in ('+
@sql+')) b) m ,
---------- ----------- ----------- -----------
张三 74 83 93
李四 74 84 94
2、使用SQL Server 2000静态SQL
--SQL SERVER 2000静态SQL。
注意:PIVOT、UNPIVOT是SQL Server 2005 的语法,使用需修改数据库兼容级别
在数据库属性->选项->兼容级别改为 90
典型实例
一、行转列
1、建立表格
ifobject_id('tb')isnotnulldroptabletb
go
createtabletb(姓名varchar(10),课程varchar(10),分数int)
insertintotbvalues('张三','语文',74)
insertintotbvalues('张三','数学',83)
insertintotbvalues('张三','物理',93)
insertintotbvalues('李四','语文',74)
insertintotbvalues('李四','数学',84)
李四 84 94 74
张三 83 93 74
4、使用SQL Server 2005静态SQL
select*fromtb pivot(max(分数)for课程in(语文,数学,物理))a
张三 74 83 93 250 83.33
2、使用SQL Server 2000动态SQL
--SQL SERVER 2000动态SQL
declare@sqlvarchar(500)
set@sql='select姓名'
go
createtabletb(姓名varchar(10),语文int,数学int,物理int)
insertintotbvalues('张三',74,83,93)
insertintotbvalues('李四',74,84,94)
go
select*fromt5、使用SQL Server 2005动态SQL
--使用stuff()
declare@sqlvarchar(8000)
set@sql='' --初始化变量@sql
select@sql=@sql+','+课程fromtbgroupby课程--变量多值赋值
set@sql=stuff(@sql,1,1,'')--去掉首个','
max(case课程when'数学'then分数else0end)数学,
max(case课程when'物理'then分数else0end)物理
fromtb
groupby姓名
姓名 语文 数学 物理
---------- ----------- ----------- -----------
姓名 课程 分数
---------- ---- -----------
李四 语文 74
李四 数学 84
李四 物理 94
张三 语文 74
张三 数学 83
张三 物理 93
2、使用SQL Server 2000动态SQL
select@sql=@sql+',max(case课程when '''+课程+''' then分数else 0 end)['+课程+']'
from(selectdistinct课程fromtb)a
set@sql=@sql+',sum(分数)总分,cast(avg(分数*1.0) as decimal(18,2)) 平均分from tb group by姓名'
--同select @sql = @sql + ','+课程from (select distinct课程from tb)a
set@sql=stuff(@sql,1,1,'')--去掉首个','
set@sql='select m.* , n.总分,n.平均分from
(select * from (select * from tb) a pivot (max(分数) for课程in ('+@sql+')) b) m ,
select*from
(
select姓名,课程='语文',分数=语文fromtb
unionall
select姓名,课程='数学',分数=数学fromtb
unionall
select姓名,课程='物理',分数=物理fromtb
) t
orderby姓名,case课程when'语文'then1when'数学'then2when'物理'then3end
set@sql='select * from tb pivot (max(分数) for课程in ('+@sql+'))a'
exec(@sql)
二、行转列结果加上总分、平均分
1、使用SQL Server 2000静态SQL
--SQL SERVER 2000静态SQL
select姓名,
(select姓名,sum(分数)总分, cast(avg(分数*1.0) as decimal(18,2))平均分from tb group by姓名) n
where m.姓名= n.姓名'
exec(@sql)
--或使用isnull()
declare@sqlvarchar(8000)
--SQL SERVER 2000动态SQL。
--调用系统表动态生态。
declare@sqlvarchar(8000)
select@sql=isnull(@sql+' union all ','')+' select姓名, [课程]='
exec(@sql)
3、使用SQL Server 2005静态SQL
selectm.*,n.总分,n.平均分
from
(select*fromtb pivot(max(分数)for课程in(语文,数学,物理))a)m,
(select姓名,sum(分数)总分,cast(avg(分数*1.0)asdecimal(18,2))平均分
insertintotbvalues('李四','物理',94)
go
select*fromtb
go
姓名 课程 分数
---------- ---------- -----------
张三 语文 74
张三 数学 83
fromtb
groupby姓名
姓名 语文 数学 物理 总分 平均分
---------- ----------- ----------- ----------- -----------
李四 74 84 94 252 84.00
from(selectdistinct课程fromtb)asa
set@sql='select姓名,'+@sql+' from tb group by姓名'
exec(@sql)
姓名 数学 物理 语文
---------- ----------- ----------- -----------
PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现
PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P
完整语法:
table_source
PIVOT(
聚合函数(value_column)