==========行转列(PIVOT函数求解)=========

wing7742 2011-12-03 11:48:19
近日在处理行转列时遇到困惑,特向C友们求解。
测试数据如下:

CREATE TABLE A
(
uid INT,
pname CHAR(4),
pcount INT,
pmoney INT
)

CREATE TABLE B
(
deptID INT,
groupID INT,
uid int
)

INSERT a
SELECT 1,'A',1,2 UNION ALL
SELECT 2,'B',1,4 UNION ALL
SELECT 3,'A',1,2 UNION ALL
SELECT 1,'A',1,2 UNION ALL
SELECT 1,'A',1,2 UNION ALL
SELECT 2,'A',1,2 UNION ALL
SELECT 3,'B',1,4 UNION ALL
SELECT 1,'A',1,2 UNION ALL
SELECT 1,'A',1,2

INSERT b
SELECT 1,1,1 UNION ALL
SELECT 1,1,2 UNION ALL
SELECT 1,2,3

结果要求:
deptid groupid uid A A _count B B _count
----------- ----------- ----------- ----------- ----------- ----------- -----------
1 1 1 10 5 0 0
1 1 2 2 1 4 1
1 2 3 2 1 4 1


解决方案:
DECLARE @sql NVARCHAR(MAX)

SELECT @sql=ISNULL(@sql+',','')+QUOTENAME(pname)+'=sum(case when pname=N'+QUOTENAME(pname,'''')+'
then pmoney else 0 end),'+QUOTENAME(pname+'_count')+'=sum(case when pname=N'+QUOTENAME(pname,'''')+'
then pcount else 0 end)' FROM a GROUP BY pname

SET @sql='select b.deptid,b.groupid,t.* from b left join(select uid,'+@sql+' from a group by uid) t on t.uid=b.uid'

EXEC(@sql)

问题:
PIVOT能否实现?如何采用PIVOT实现?
...全文
203 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
--小F-- 2011-12-03
  • 打赏
  • 举报
回复
*
标题:普通行列转换(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')

---------------------------------

/*
问题:在上述结果的基础上加平均分,总分,得到如下结果:
姓名 语文 数学 物理 平均分 总分
---- ---- ---- ---- ------ ----
李四 74 84 94 84.00 252
张三 74 83 93 83.33 250
*/

--SQL SERVER 2000 静态SQL。
select 姓名 姓名,
max(case 课程 when '语文' then 分数 else 0 end) 语文,
max(case 课程 when '数学' then 分数 else 0 end) 数学,
max(case 课程 when '物理' then 分数 else 0 end) 物理,
cast(avg(分数*1.0) as decimal(18,2)) 平均分,
sum(分数) 总分
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 + ' , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名'
exec(@sql)

--SQL SERVER 2005 静态SQL。
select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b) m,
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名

--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + ',' , '') + 课程 from tb group by 课程
exec ('select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b) m ,
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名')

drop table tb

------------------
------------------
中国风 2011-12-03
  • 打赏
  • 举报
回复
楼主这样写就行了,如果是单列 行转列可用pivot,大于1列不推荐用pivot

参照例子
http://topic.csdn.net/u/20080614/17/22e73f33-f071-46dc-b9bf-321204b1656f.html
快溜 2011-12-03
  • 打赏
  • 举报
回复
CREATE TABLE A
(
uid INT,
pname varCHAR(4),
pcount INT,
pmoney INT
)

CREATE TABLE B
(
deptID INT,
groupID INT,
uid int
)

INSERT a
SELECT 1,'A',1,2 UNION ALL
SELECT 2,'B',1,4 UNION ALL
SELECT 3,'A',1,2 UNION ALL
SELECT 1,'A',1,2 UNION ALL
SELECT 1,'A',1,2 UNION ALL
SELECT 2,'A',1,2 UNION ALL
SELECT 3,'B',1,4 UNION ALL
SELECT 1,'A',1,2 UNION ALL
SELECT 1,'A',1,2

INSERT b
SELECT 1,1,1 UNION ALL
SELECT 1,1,2 UNION ALL
SELECT 1,2,3


DECLARE @sql NVARCHAR(1000), @sql1 NVARCHAR(1000),@sql2 NVARCHAR(1000)
SELECT @sql1=ISNULL(@sql1+',','')+QUOTENAME(pname) FROM a GROUP BY pname
SELECT @sql2=ISNULL(@sql2+',','')+QUOTENAME(pname+'_count') FROM a GROUP BY pname
SET @sql='select * from b m left join
(select * from (select uid,pname,pmoney from a) x pivot (sum(pmoney)
for pname in ('+@sql1+'))t) n on m.uid=n.uid
left join (select * from (select uid,pname+''_count'' pname,pcount from a) x pivot
(sum(pcount) for pname in ('+@sql2+'))s) o on m.uid=o.uid'
print @sql
EXEC(@sql)

/*
deptID groupID uid uid A B uid A_count B_count
----------- ----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
1 1 1 1 10 NULL 1 5 NULL
1 1 2 2 2 4 2 1 1
1 2 3 3 2 4 3 1 1

(3 行受影响)
AcHerat 2011-12-03
  • 打赏
  • 举报
回复
对PIVOT而言还是要动态去做,依旧是拼接字符串。
-晴天 2011-12-03
  • 打赏
  • 举报
回复
要用pivot ,先得整理成可以供它用的形式.
pengxuan 2011-12-03
  • 打赏
  • 举报
回复
PIVOT 也需要动态拼SQL字符串
wing7742 2011-12-03
  • 打赏
  • 举报
回复
看来是我想太多了 以为PIVOT有什么特殊要求 还是老老实实的拼字符串吧
光盘中的内容 ------------------------------------------------------------------------ 下面的部分提供光盘中各种资源的详细信息。 本书中的实例文件 本书中使用的文件是按章节组织的,除了几个例外,所有文件都是带有以下扩展名的Excel 2007文件: * ? XLSX:Excel工作簿文件 * ? XLSM:包含VBVA宏的Excel工作簿文件 当打开XLSM文件时,Excel可能会显示安全警告并告诉您已禁用宏。要启用宏,单击 “安全警告”面板中的“选项”按钮然后选择“启用此内容”选项。 由于光盘上的文件是来自受信任源,您可以将这些文件复制到您的电脑上,然后指定一个文件夹作为受信任位置,要想这样,执行以下操作: 1. 打开一个“资源管理器”窗口,选择包含附带光盘的光驱。 2. 右击带有实例的根文件夹相应的文件夹,并从快捷菜单中选择“复制”命令。 3. 激活电脑中要复制文件的目标文件夹,右击该目录并从快捷菜单中选择“粘贴”命令。 光盘上的文件将会被复制到在第3步中指定的文件夹的子文件夹中,要指定一个新文件夹作为信任中心,执行以下步骤: 1. 打开Excel并选择“Office按钮”-“Excel选项”命令以显示“Excel选项”对话框。 2. 在“Excel选项”对话框中,单击“信任中心”选项卡。 3. 单击“信任中心设置”按钮。 4. 在“信任中心”对话框中,单击“受信任位置”选项卡。 5. 单击“添加新位置”按钮以显示“Microsoft Office受信任中心”对话框。 6. “Microsoft Office受信任中心”对话框中,单击“浏览”按钮并查找包含从光盘上复制过来的文件夹。 7. 确保选择“同时信任此位置的子文件夹”。 执行这些步骤后,当从该位置选择XLSM文件时,宏已启用,这样就不会看见安全警告了。 下面列举了一些实例文件和一些简单的描述。 注意:有些章节中没有实例。 Chapter 01 table and chart.xlsx:一个简单的创建表和图表的介绍性实例。 Chapter 03 loan payment calculator.xlsx:演示公式的工作簿。 number formatting.xlsx:包含一些内置数字格式实例的工作簿。 Chapter 05 budget.xlsx:演示在工作表中使用的格式的一个简单的多工作表预算工作簿。 Chapter 06 real estate table.xlsx:包含实际使用表格的real estate列表的工作簿。 Chapter 07 loan payments.xlsx:包含演示应用简单格式效果的数据区域和公式的工作簿。 theme examples.xlsx:包含表、SmartArt和一个图表的工作簿,用于演示应用不同文件主题后的效果。 Chapter 11 cell references.xlsx:用于演示复制公式时使用不同类型单元格引用的效果的工作簿。 circular reference.xlsx:一个演示目的循环引用的工作簿。打开这个工作簿时,会看见有关循环引用的信息。 worksheet functions.xlsx:包含一个列举和描述了每个工作表函数的表的工作簿。 table formulas.xlsx:用于演示表内公式的使用的工作簿 Chapter 12 character set.xlsx:一个以任意安装在系统中的字体显示字符的工作簿。 text formula examples.xlsx:一个包含高级文本公式例子的工作簿。 text histogram.xlsx:一个包含两个直接在区域中创建柱状图的例子的工作簿。 Chapter 13 holidays.xlsx:一个演示了如何计算美国10个年假日的工作簿。 jogging log.xlsx:一个记录时间和慢跑过程的工作簿。演示了时间的使用和一天的某个时间没有直接联系。 time sheet.xlsx:一个记录每周工作时间的工作表。 work days.xlsx:一个演示了如果计算两个日期之间的工作天数的工作簿(除了周末和假期以外)。 Chapter 14 basic counting.xlsx:一个演示基本的计算公式的工作簿。 conditional summing.xlsx:一个演示如何使用单个或多个条件计算进行条件求和的工作簿。 cout unique.xlsx:一个演示如何计算区域内惟一(非复制的)项的工作簿。 counting text in a range.xlsx:一个演示计算区域内字符数量的各种方式的工作簿。 cumulative sum.xlsx:一个演示如何计算一个累积和的工作簿。 frequency distribution.xlsx:一个演示创建频率分布的四种方法的工作簿。 multiple criteria counting.xlsx:一个演示使用多个条件计算公式的工作簿。 Chapter 15 basic lookup examples.xlsx:一个演示基本的查找技巧的工作簿。 specialized lookup examples.xlsx:一个演示特殊的查找技巧的工作簿。 Chapter 16 annuity calculator.xlsx:一个计算养老金利润的工作簿。 credit card payments.xlsx:一个包含计算信用卡付款的公式的工作簿。 depreciation.xlsx:一个演示计算资产折旧的方法的工作簿。 investment calculations.xlsx:一个演示计算投资利润的公式的工作簿。 irregular payments.xlsx:一个演示不规则还款的贷款计算的工作簿。 loan amortization schedule.xlsx:一个计算贷款分期偿还时间表的工作簿。 loan data tables.xlsx:一个演示如何使用一种方法和两种方法计算数据表中的贷款。 loan payment.xlsx:一个包含计算贷款还款的公式的工作簿。 Chapter 18 calendar array.xlsx:一个演示如何使用复杂的数组公式在区域中显示一个月的日历的工作簿。 multi-cell array formulas.xlsx:一个演示多单元格数组公式的工作簿。 single-cell array formulas.xlsx:一个演示单个单元格数组公式的工作簿。 Chapter 19 area charts.xlsx:一个包含面积图表例子的工作簿。 bar charts.xlsx:一个包含条形图表例子的工作簿。 bubble charts.xlsx:一个包含气泡图例子的工作簿。 column charts.xlsx:一个包含柱形图例子的工作簿。 cylinder cone pyramid charts.xlsx:圆柱、圆锥和棱锥图例子。 doughnut charts.xlsx:圆环图例子。 hands-on example.xlsx:一个包含在一个简单的图表例子的数据的工作簿。 line charts.xlsx:一个包含折线图例子的工作簿。 pie charts.xlsx:一个包含饼图例子的工作簿。 radar charts.xlsx:一个包含雷达图例子的工作簿。 six chart types.xlsx:一个使用6种图表类型显示相同区域的工作簿。 stock charts.xlsx:一个包含股价图例子的工作簿。 surface charts.xlsx:一个包含曲面图例子的工作簿。 xy charts.xlsx:一个包含XY散点图例子的工作簿。 Chapter 20 comparative histogram.xlsx:一个演示如何创建比较柱状图的工作簿。 conditional colors.xlsx:一个包含根据数值显示不同颜色的柱形图的工作簿。 function plot 2D.xlsx:一个演示如何使用一个变量的函数绘图的工作簿。 function plot 3D.xlsx:一个演示如何使用两个变量的函数绘图的工作簿。 gantt.xlsx:一个演示如何创建简单的有关工程方案的甘特图的工作簿。 gauge chart.xlsx:一个包含将单数据点绘制成量表的图表的工作簿。 log scale.xlsx:一个演示图表中的对数标度的工作簿。 picture charts.xlsx:一个演示在图表中使用图片的工作簿。 single data point charts.xlsx:演示各种单数据点例子,包括温度计图和标准尺图。 thermometer chart.xlsx:一个包含将单数据点绘制成温度计的图表的工作簿。 weather combination chart.xlsx:一个演示使用两个数值轴的合并图表的工作簿。 Chapter 21 daily staffing levels.xlsx:一个演示设置条件格式的颜色刻度的工作簿。 conditional formatting formulas.xlsx:一个演示条件格式公式的工作簿。 data bars examples.xlsx:一个演示较大区域中的设置条件格式的颜色刻度的工作簿。 icon set examples.xlsx:一个演示设置条件格式的图标设置的工作簿。 Chapter 24 number formats.xlsx:一个包含许多自定义格式例子的工作簿。 Chapter 25 data validation examples.xlsx:一个包含数据有效性例子的工作簿。 Chapter 26 outline example.xlsx:一个包含适用分组显示的数据的工作簿。 Chapter 27 regionl.xlsx:用于演示数据合并的三个工作表之一。 region2.xlsx:用于演示数据合并的三个工作表之一。 region3.xlsx:用于演示数据合并的三个工作表之一。 Chapter 28 webpage.xlsx:一个用于演示HTML输出的工作簿。 Chapter 33 budget data.accdb:惟一一个Microsoft Access 2007文件,用于演示Microsoft查询。 Chapter 34 bank accounts.xlsx:一个包含适用于数据透视表的数据的工作簿。 Chapter 35 calculated fields and items.xlsx:一个包含演示计算字段和计算项的数据透视表的工作簿。 county data.xlsx:一个包含一个大表格和从表中创建的数据透视表的工作簿。 employee list.xlsx:一个包含演示数据透视表中非数字型数据的表格的工作簿。 hourly readings.xlsx:一个包含演示按时间分组的时间信息的工作簿。 income and expense.xlsx:一个包含演示如何在数据透视表内引用单元格的数据透视表的工作簿。 music list.xlsx:一个演示如何创建和格式化数据透视表报表的工作簿。 reverse pivot.xlsm:一个包含将汇总表转换为3列数据库表的VBA宏的工作簿。 sales by date.xlsx:一个包含演示按时间分组的时间信息的工作簿。 sales by region.xlsx:一个演示如何从数据透视表中创建透视图的工作簿。 test scores.xlsx:一个演示如何使用数据透视表创建频率分布的工作簿。 Chapter 36 direct mail.xlsx:一个包含演示如何创建两种方式的假设分析数据表的利润模型。 mortgage loan data table.xlsx:一个演示如何创建一种方式的假设分析数据表的工作簿。 mortgage loan.xlsx:一个使用输入单元格和公式单元格演示假设分析过程的工作簿。 production model.xlsx:一个演示方案管理器的工作簿。 Chapter 37 allocating resources.xlsx:一个包含演示如何分配资源和使用“规划求解”来最大化利润的模型的工作簿。 investment portfolio.xlsx:一个包含演示如何使用“规划求解”来最大化投资项目利润的模型的工作簿。 linear equations.xlsx:一个演示如何使用“规划求解”解决一组线性方程式的工作簿。 mortgage loan.xlsx:一个使用输入单元格和公式单元格进行单变量求解的工作簿。 three products.xlsx:一个包含演示“规划求解”过程的简单模型的工作簿。 Chapter 38 atp examples.xlsx:演示在“分析工具库”加载项中使用的工具的工作簿。 Chapter 39 cube root.xlsm:一个包含计算立方根的VBA函数的工作簿。 current date.xlsm:一个包含用来在活动单元格插入一个当前日期的简单VBA宏的工作簿。 list formulas.xlsm:一个包含用来在工作表中生成一个所有公式列表的VBA宏的工作簿。 Chapter 40 vba functions.xlsm:一个包含用于工作表公式的VBA函数的工作簿。 Chapter 41 change case.xlsm:使用UserForm以让用户进行选择的VBA宏。 show message.xlsm:一个包含显示信息的UserForm的工作簿。 Chapter 42 mortgage loan.xlsx:一个演示如何使用一个工作表中的ActiveX控件的工作簿。 worksheet controls.xlsm:一个包含所有用于一个工作表的ActiveX控件的例子的工作簿。 Chapter 43 monitor a range.xlsm:一个包含VBA Worksheet_Change宏用于控制指定区域的所有更改的工作簿。 selection change event.xlsm:一个包含VBA Worksheet_Change宏用于更改活动单元格行和列颜色的工作簿。 Chapter 44 chart macros.xlsm:一个包含计算图表的VBA宏的工作簿。 range copy.xlsm:一个包含复制一个大小不固定区域的VBA宏的工作簿。 range move.xlsm:一个包含移动单元格区域的VBA宏的工作簿。 select cells.xlsm:一个包含演示选中区域技巧的VBA宏的工作簿。 selection type.xlsm:一个包含演示如何确定当前选中区域的对象类型的VBA宏的工作簿。 skip blanks while looping.xlsm:一个包含演示如何在单元格区域中有效循环的VBA宏的工作簿。 Chapter 45 change case.xlam:一个从Chapter 41中change case.xlsm例子中创建的加载项文件。

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧