表结构:
列: ClassID StudentName
1 a1
1 a2
2 a1
3 a2
2 d1
4 d1
3 a3
1 b2 希望输出结果: 不同 student分不同列,student最多2列
列: ClassID Student1 Student2 Student3(不显示)
1 a1 a2 b2(不显示)
2 a1 d1
3 a2 a3
4 d1 (不显示)
找了好久,网上的例子都是把student按字符串放在一列。小弟在线等。
谢谢
列: ClassID StudentName
1 a1
1 a2
2 a1
3 a2
2 d1
4 d1
3 a3
1 b2 希望输出结果: 不同 student分不同列,student最多2列
列: ClassID Student1 Student2 Student3(不显示)
1 a1 a2 b2(不显示)
2 a1 d1
3 a2 a3
4 d1 (不显示)
找了好久,网上的例子都是把student按字符串放在一列。小弟在线等。
谢谢
解决方案 »
- 一个sql语句不 会写
- 发票和收款的匹配
- sql语句的问题
- 可以新建一个别的名称的超级用户,然后删除sa 用户吗?因为sa这个名称谁都知道,不安全.或者保留sa,但是让它没有高权限,可以实现吗?会存在问题吗?
- SQL Server中两个表的连接查询,其中一个表中的一个字段是另一个表的主键,如果此表中这列的值不为空,则执行连接查询,查询另一个表中的别的某个字段的值
- grant execute to ...
- MS SQL 2000 取每一组的三位最低数据 SQL 语句怎么写啊 并且行转列
- 请教:我这样建立数据库的备份合理吗?
- 用VB.NET和SQL做的数据库应用程序应怎么做安装文件?
- 妈的SQL SERVER 天天出错,请知道的大哥告诉我这个GROUP BY 的BUG 如何解决
- 为字段设置主键
- 求一条SQL语句
/*
标题:普通行列转换(version 2.0)
说明:普通行列转换(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 课程
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.姓名')
if object_id('[TB]') is not null drop table [TB]
create table [TB]([ClassID] int,[StudentName] varchar(2))
insert [TB]
select 1,'a1' union all
select 1,'a2' union all
select 2,'a1' union all
select 3,'a2' union all
select 2,'d1' union all
select 4,'d1' union all
select 3,'a3' union all
select 1,'b2'select * from [TB]SELECT classid,
[STU1] = CASE WHEN studentname = 'a1' THEN studentname ELSE '' END,
[STU2] = CASE WHEN studentname = 'a2' THEN studentname ELSE '' END
FROM dbo.TB
GROUP BY classid,studentname
SELECT classid,studentname AS STU1,STU2 = (SELECT TOP 1 studentname FROM tb WHERE A.classid = classid and tb.studentname <>A.studentname ORDER BY studentname asc)
FROM dbo.TB A
WHERE studentname IN (SELECT TOP 1 studentname FROM tb WHERE A.classid = classid ORDER BY studentname asc)/*
classid STU1 STU2
1 a1 a2
2 a1 d1
3 a2 a3
4 d1 NULL*/
FROM dbo.TB A
WHERE studentname IN (SELECT TOP 1 studentname FROM tb WHERE A.classid = classid ORDER BY studentname asc)光这个,中间乱写的也发上来了哈。
create table [TB]([ClassID] int,[StudentName] varchar(2))
insert [TB]
select 1,'a1' union all
select 1,'a2' union all
select 2,'a1' union all
select 3,'a2' union all
select 2,'d1' union all
select 4,'d1' union all
select 3,'a3' union all
select 1,'b2'
goselect ClassID ,
max(case px when 1 then StudentName else '' end) StudentName1,
max(case px when 2 then StudentName else '' end) StudentName2
from
(
select * , px = (select count(1) from tb where ClassID = t.ClassID and StudentName < t.StudentName) + 1 from tb t
) m
group by ClassIDdrop table tb/*
ClassID StudentName1 StudentName2
----------- ------------ ------------
1 a1 a2
2 a1 d1
3 a2 a3
4 d1 (所影响的行数为 4 行)
*/
--sql 2005
select ClassID ,
max(case px when 1 then StudentName else '' end) StudentName1,
max(case px when 2 then StudentName else '' end) StudentName2
from
(
select * , px = row_number() over(partition by ClassID order by StudentName) from tb t
) m
group by ClassID
另外,如何确保classid为1时,输出的为a1,a2,而不是a2,b2呢
我觉得lz没有把题目说明白
列: ClassID StudentName
1 a1
1 a2
2 a1
3 a2
2 d1
4 d1
3 a3
1 b2 希望输出结果: 不同 student分不同列,student最多2列
列: ClassID Student1 Student2 Student3(不显示)
1 a1 a2 b2(不显示)
2 a1 d1
3 a2 a3
4 d1 (不显示)
找了好久,网上的例子都是把student按字符串放在一列。
做法:
declare @li_class integer
declare @li_cnt integer
create table #tmp(ClassID int,Student1 varchar(20),Student2 varchar(20))
declare cur cursor for
select distinct ClassID from tt --tt所有的ClassID
open cur
fetch next from cur into @li_class
while @@fetch_status=0
begin
set @li_cnt=(select count(ClassID) from tt where ClassID=@li_class)
if @li_cnt=2
begin
--将两行合并成一行,放到临时表中#tmp
insert into #tmp(ClassID,Student1,Student2) select top 1 a.ClassID,a.StudentName as Student1,b.StudentName as Student2 from tt a inner join tt b on a.ClassID=b.ClassID and a.StudentName<>b.StudentName and ClassID=@li_class
end
fetch next from cur into @li_class
end
select * from #tmp
--删除临时表#tmp
if object_id('tempdb..#tmp') is not null
begin
drop table #tmp
end