很久没上CSDN了,今天来报个到 + 提个问

zpcoder 2010-04-06 04:19:12
已有数据表如下:
id dt vl nt
---------------------------------------------
1234 2010-04-06 08:01:23.000 26.240 xyz
1234 2010-04-06 09:01:23.000 77.133 xyz
1234 2010-04-06 10:01:23.000 19.810 xyz
1234 2010-04-06 11:01:23.000 38.627 xyz
1234 2010-04-06 12:01:23.000 82.867 xyz
1234 2010-04-06 13:01:23.000 9.107 xyz
1234 2010-04-06 14:01:23.000 75.103 xyz
1234 2010-04-06 15:01:23.000 3.259 xyz
1235 2010-04-06 15:32:48.000 360.000 xyz
1235 2010-04-06 16:01:23.000 98.426 xyz
……

按 datepart(hh,dt) 进行行列转换并加上最大最小和这个时间段的平均值
结果要:
id 8 9 10 …… max min avg
---------------------------------------------------
1234 26.24 77.133 19.81 360.0 3.259 *
...全文
129 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
htl258_Tony 2010-04-06
  • 打赏
  • 举报
回复
--------------------------------------------------------------------------
-- Author : htl258(Tony)
-- Date : 2010-04-06 18:54:30
-- Version:Microsoft SQL Server 2008 (SP1) - 10.0.2531.0 (Intel X86)
-- Mar 29 2009 10:27:29
-- Copyright (c) 1988-2008 Microsoft Corporation
-- Developer Edition on Windows NT 5.1 <X86> (Build 2600: Service Pack 2)
--------------------------------------------------------------------------
--> 生成测试数据表:tb

IF NOT OBJECT_ID('[tb]') IS NULL
DROP TABLE [tb]
GO
CREATE TABLE TB(ID INT,DT DATETIME,VL DECIMAL(18,3),NT VARCHAR(10))
INSERT INTO TB VALUES(1234 , '2010-04-06 08:01:23.000' , 26.240 , 'XYZ')
INSERT INTO TB VALUES(1234 , '2010-04-06 09:01:23.000' , 77.133 , 'XYZ')
INSERT INTO TB VALUES(1234 , '2010-04-06 10:01:23.000' , 19.810 , 'XYZ')
INSERT INTO TB VALUES(1234 , '2010-04-06 11:01:23.000' , 38.627 , 'XYZ')
INSERT INTO TB VALUES(1234 , '2010-04-06 12:01:23.000' , 82.867 , 'XYZ')
INSERT INTO TB VALUES(1234 , '2010-04-06 13:01:23.000' , 9.107 , 'XYZ')
INSERT INTO TB VALUES(1234 , '2010-04-06 14:01:23.000' , 75.103 , 'XYZ')
INSERT INTO TB VALUES(1234 , '2010-04-06 15:01:23.000' , 3.259 , 'XYZ')
INSERT INTO TB VALUES(1235 , '2010-04-06 15:32:48.000' , 360.000 , 'XYZ')
INSERT INTO TB VALUES(1235 , '2010-04-06 16:01:23.000' , 98.426 , 'XYZ')
GO

select id,ISNULL([0],0) [0],ISNULL([1],0) [1],ISNULL([2],0) [2],ISNULL([3],0) [3],ISNULL([4],0) [4],ISNULL([5],0) [5],
ISNULL([6],0) [6],ISNULL([7],0) [7],ISNULL([8],0) [8],ISNULL([9],0) [9],ISNULL([10],0) [10],ISNULL([11],0) [11],
ISNULL([12],0) [12],ISNULL([13],0) [13],ISNULL([14],0) [14],ISNULL([15],0) [15],ISNULL([16],0) [16],ISNULL([17],0) [17],
ISNULL([18],0) [18],ISNULL([19],0) [19],ISNULL([20],0) [20],ISNULL([21],0) [21],ISNULL([22],0) [22],ISNULL([23],0) [23],
maxvl,minvl,avgvl
from (
select ID,DATEPART(hh,dt) dt,vl,
MAX(vl)over(partition by id) maxvl,
MIN(vl)over(partition by id) minvl,
AVG(vl)over(partition by id) avgvl
from tb
) t
pivot(max(vl) for dt in(
[0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],
[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23])) b
/*
id 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 maxvl minvl avgvl
----------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- ---------------------------------------
1234 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 26.240 77.133 19.810 38.627 82.867 9.107 75.103 3.259 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 82.867 3.259 41.518250
1235 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 360.000 98.426 0.000 0.000 0.000 0.000 0.000 0.000 0.000 360.000 98.426 229.213000

(2 行受影响)
*/
顺便写个05的
老黎 2010-04-06
  • 打赏
  • 举报
回复
围观行转列
记住四个关键字就搞定了
case when 和 unon all
剩下的就是慢慢地做了
feixianxxx 2010-04-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 happyflystone 的回复:]
SF


---


select id,sum(case when datepart(hh,dt) = 8 then vl else 0 end) as [8],
sum(case when datepart(hh,dt) = 8 then vl else 0 end) as [9],
sum(case when datepart(hh,dt) = 8 then vl else ……
[/Quote]
。。
SQL77 2010-04-06
  • 打赏
  • 举报
回复
...............
喜-喜 2010-04-06
  • 打赏
  • 举报
回复
--“行列转换”之PIVOT/UNPIVOT的用法  
--
-- 使用过SQL Server 2000的人都知道,要想实现行列转换,必须综合利用聚合函数和动态SQL,具体实现起来需要一定的技巧,而在SQL Server 2005中,使用新引进的关键字PIVOT/UNPIVOT,则可以很容易的实现行列转换的需求。
--
--在本文中我们将通过两个简单的例子详细讲解PIVOT/UNPIVOT的用法。
--
--PIVOT的用法:
--
--首先创建测试表,然后插入测试数据

create table test(id int,name varchar(20),quarter int,profile int)
insert into test values(1,'a',1,1000)
insert into test values(1,'a',2,2000)
insert into test values(1,'a',3,4000)
insert into test values(1,'a',4,5000)
insert into test values(2,'b',1,3000)
insert into test values(2,'b',2,3500)
insert into test values(2,'b',3,4200)
insert into test values(2,'b',4,5500)
select * from test
--id name quarter profile
----------- -------------- ----------- -----------
--1 a 1 1000
--1 a 2 2000
--1 a 3 4000
--1 a 4 5000
--2 b 1 3000
--2 b 2 3500
--2 b 3 4200
--2 b 4 5500
--(8 row(s) affected)
--使用PIVOT将四个季度的利润转换成横向显示:
select id,name,
[1] as "一季度",
[2] as "二季度",
[3] as "三季度",
[4] as "四季度"
from
test
pivot
(
sum(profile)
for quarter in
([1],[2],[3],[4])
)
as pvt
--id name 一季度 二季度 三季度 四季度
-------- --------- ----------- -------- ------- -------
--1 a 1000 2000 4000 5000
--2 b 3000 3500 4200 5500
--(2 row(s) affected)


--UNPIVOT的用法:

--首先建立测试表,然后插入测试数据
drop table test
create table test(id int,name varchar(20), Q1 int, Q2 int, Q3 int, Q4 int)
insert into test values(1,'a',1000,2000,4000,5000)
insert into test values(2,'b',3000,3500,4200,5500)
select * from test
--id name Q1 Q2 Q3 Q4
-------- ------- --------- --------- -------- --------
--1 a 1000 2000 4000 5000
--2 b 3000 3500 4200 5500
--(2 row(s) affected)
--使用UNPIVOT,将同一行中四个季度的列数据转换成四行数据:
select id,name,quarter,profile
from
test
unpivot
(
profile
for quarter in
([Q1],[Q2],[Q3],[Q4])
)
as unpvt
--id name quarter profile
----------- ----------- ---------- -----------
--1 a Q1 1000
--1 a Q2 2000
--1 a Q3 4000
--1 a Q4 5000
--2 b Q1 3000
--2 b Q2 3500
--2 b Q3 4200
--2 b Q4 5500
--(8 row(s) affected)
huangheguyun 2010-04-06
  • 打赏
  • 举报
回复
CSDN里面搜一下经典的例子,有的是。
zhousq00 2010-04-06
  • 打赏
  • 举报
回复
唉!!!!
行列转换
永远的貌似简单
实际很难
但确实又有很多方法的问题
dawugui 2010-04-06
  • 打赏
  • 举报
回复
create table tb(id int,dt datetime,vl decimal(18,3),nt varchar(10))
insert into tb values(1234 , '2010-04-06 08:01:23.000' , 26.240 , 'xyz')
insert into tb values(1234 , '2010-04-06 09:01:23.000' , 77.133 , 'xyz')
insert into tb values(1234 , '2010-04-06 10:01:23.000' , 19.810 , 'xyz')
insert into tb values(1234 , '2010-04-06 11:01:23.000' , 38.627 , 'xyz')
insert into tb values(1234 , '2010-04-06 12:01:23.000' , 82.867 , 'xyz')
insert into tb values(1234 , '2010-04-06 13:01:23.000' , 9.107 , 'xyz')
insert into tb values(1234 , '2010-04-06 14:01:23.000' , 75.103 , 'xyz')
insert into tb values(1234 , '2010-04-06 15:01:23.000' , 3.259 , 'xyz')
insert into tb values(1235 , '2010-04-06 15:32:48.000' , 360.000 , 'xyz')
insert into tb values(1235 , '2010-04-06 16:01:23.000' , 98.426 , 'xyz')
go
--静态的.
select id ,
max(case datepart(hh,dt) when 0 then vl else 0 end) [0],
max(case datepart(hh,dt) when 1 then vl else 0 end) [1],
max(case datepart(hh,dt) when 2 then vl else 0 end) [2],
max(case datepart(hh,dt) when 3 then vl else 0 end) [3],
max(case datepart(hh,dt) when 4 then vl else 0 end) [4],
max(case datepart(hh,dt) when 5 then vl else 0 end) [5],
max(case datepart(hh,dt) when 6 then vl else 0 end) [6],
max(case datepart(hh,dt) when 7 then vl else 0 end) [7],
max(case datepart(hh,dt) when 8 then vl else 0 end) [8],
max(case datepart(hh,dt) when 9 then vl else 0 end) [9],
max(case datepart(hh,dt) when 10 then vl else 0 end) [10],
max(case datepart(hh,dt) when 11 then vl else 0 end) [11],
max(case datepart(hh,dt) when 12 then vl else 0 end) [12],
max(case datepart(hh,dt) when 13 then vl else 0 end) [13],
max(case datepart(hh,dt) when 14 then vl else 0 end) [14],
max(case datepart(hh,dt) when 15 then vl else 0 end) [15],
max(case datepart(hh,dt) when 16 then vl else 0 end) [16],
max(case datepart(hh,dt) when 17 then vl else 0 end) [17],
max(case datepart(hh,dt) when 18 then vl else 0 end) [18],
max(case datepart(hh,dt) when 19 then vl else 0 end) [19],
max(case datepart(hh,dt) when 20 then vl else 0 end) [20],
max(case datepart(hh,dt) when 21 then vl else 0 end) [21],
max(case datepart(hh,dt) when 22 then vl else 0 end) [22],
max(case datepart(hh,dt) when 23 then vl else 0 end) [23],
max(vl) [max],
min(vl) [min],
avg(vl) [avg]
from tb group by id
/*
id 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 max min avg
----------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- ----------------------------------------
1234 .000 .000 .000 .000 .000 .000 .000 .000 26.240 77.133 19.810 38.627 82.867 9.107 75.103 3.259 .000 .000 .000 .000 .000 .000 .000 .000 82.867 3.259 41.518250
1235 .000 .000 .000 .000 .000 .000 .000 .000 .000 .000 .000 .000 .000 .000 .000 360.000 98.426 .000 .000 .000 .000 .000 .000 .000 360.000 98.426 229.213000

(所影响的行数为 2 行)

*/

--动态的.
declare @sql varchar(8000)
set @sql = 'select id '
select @sql = @sql + ' , max(case datepart(hh,dt) when ''' + cast(xs as varchar) + ''' then vl else 0 end) [' + cast(xs as varchar) + ']'
from (select distinct datepart(hh,dt) xs from tb) as a
set @sql = @sql + ' ,max(vl) [max],min(vl) [min],avg(vl) [avg]from tb group by id'
exec(@sql)
/*
id 8 9 10 11 12 13 14 15 16 max min avg
----------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- ----------------------------------------
1234 26.240 77.133 19.810 38.627 82.867 9.107 75.103 3.259 .000 82.867 3.259 41.518250
1235 .000 .000 .000 .000 .000 .000 .000 360.000 98.426 360.000 98.426 229.213000

*/

drop table tb
dawugui 2010-04-06
  • 打赏
  • 举报
回复
--静态的.
select id ,
max(case datepart(hh,dt) when 0 then vl else 0 end) [0],
max(case datepart(hh,dt) when 1 then vl else 0 end) [1],
max(case datepart(hh,dt) when 2 then vl else 0 end) [2],
...
max(case datepart(hh,dt) when 23 then vl else 0 end) [23],
max(vl) [max],
min(vl) [min],
avg(vl) [avg]
from tb group by id

--动态的.
declare @sql varchar(8000)
set @sql = 'select id '
select @sql = @sql + ' , max(case datepart(hh,dt) when ''' + cast(xs as varchar) + ''' then val else 0 end) [' + cast(xs as varchar) + ']'
from (select distinct datepart(hh,dt) xs from tb) as a
set @sql = @sql + ' ,max(vl) [max],min(vl) [min],avg(vl) [avg]from tb group by id'
exec(@sql)
dawugui 2010-04-06
  • 打赏
  • 举报
回复
--静态的.
select id ,
max(case datepart(hh,dt) when 0 then vl else 0 end) [0],
max(case datepart(hh,dt) when 1 then vl else 0 end) [1],
max(case datepart(hh,dt) when 2 then vl else 0 end) [2],
...
max(case datepart(hh,dt) when 23 then vl else 0 end) [23],
max(vl) [max],
min(vl) [min],
avg(vl) [avg]
from tb group by id
--小F-- 2010-04-06
  • 打赏
  • 举报
回复
行列转换
*
标题:普通行列转换(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

------------------
------------------
-狙击手- 2010-04-06
  • 打赏
  • 举报
回复
SF


---


select id,sum(case when datepart(hh,dt) = 8 then vl else 0 end) as [8],
sum(case when datepart(hh,dt) = 8 then vl else 0 end) as [9],
sum(case when datepart(hh,dt) = 8 then vl else 0 end) as [10],
max(val) ,min(vl),avg(vl)
from ta
group by id
sql_sf 2010-04-06
  • 打赏
  • 举报
回复
学习.
soft_wsx 2010-04-06
  • 打赏
  • 举报
回复
太简单了!百度上找下!多的是

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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