求教sql语句(急!!)(200分)

  • 主题发起人 主题发起人 Minor
  • 开始时间 开始时间
M

Minor

Unregistered / Unconfirmed
GUEST, unregistred user!
各位前辈,小弟用的是SQL server 7.有3张表如下所示:

1.(dbo.lesson)这张表用来记录课程信息。
lesson_id lesson_name
11 语文
12 英语
13 数学

2.(dbo.sutdent)这张表用来记录学生信息。
student_id student_name
1 小张
2 小李
3 小明
3(dbo.score)这张表用来记录考试成绩.
student_id lesson_id score
1 11 79
2 11 68
3 11 90
1 12 88
2 12 79
3 12 60
1 13 67
2 13 87
3 13 98

我想能不能用sql语句产生如下记录集合:
学号 姓名 语文 英语 数学
1 小张 79 88 67
2 小李 68 79 87
3 小明 90 60 98

万分感激!!!!
 
如此这般:
SELECT student_id as 学号,
Max(student_name) as 姓名,
SUM(CASE lesson_id WHEN 1 THEN score ELSE 0 END) AS 语文,
SUM(CASE lesson_id WHEN 2 THEN score ELSE 0 END) AS 英语,
SUM(CASE lesson_id WHEN 3 THEN score ELSE 0 END) AS 数学,
FROM dbo.score,dbo.student where score.dbo.student_id=student.student_id
GROUP BY student_id

可以用这个方法解决你的部分问题(课程信息表没用上),
为解决课程表活动的问题,可以根据课程表来生成上面的 SQL 语句,得在程序中用代码实现。
你也可以用一个自定义函数来做。
 
to guqs:
你的办法显然是不行的,如果课程数不确定,你的办法就。。。
to Minor:
在我做的学生选课程序中,这个问题是用存储过程作的:
1、建立临时表(根据课程数的多少来确定字段数)
Declare @Count Int,@Lesson_Id Int,@I Int,@SQL VarChar(1000),@LName char(10)
--取课程总数,也就是临时表的列数
Select @Count=Count(Lesson_ID) From Lesson

Set @SQL='Create ##List([学号] Int,[姓名] char(8)'
Set @I=0
set @Lesson_Id=0
while @I<@Count
begin
Select @Lesson_ID=Min(Lesson_ID) From Lesson Where Leson_ID>@Lesson_ID
Select @LName=Lesson_Name From Lesson Where Lesson_ID=@Lesson_ID
Set @SQL=@SQL+',['+@Name+'] Int'
Set @I=@I+1
end
Set @SQL=@SQL+')'
if exists(select * from tempdb..sysobjects where name='##List') Drop Table ##List
Exec(@SQL)
2、插入所有的有成绩的学生的纪录
Insert ##List([学号],[姓名]) Select Distinct SC.Student_ID,SU.Student_Name
From Student Su,Score Sc Where SU.Studen_ID=SC.Student_ID
3、对应课程,更新成绩
Set @I=0
set @Lesson_Id=0
while @I<@Count
begin
Select @Lesson_ID=Min(Lesson_ID) From Lesson Where Leson_ID>@Lesson_ID
Select @LName=Lesson_Name From Lesson Where Lesson_ID=@Lesson_ID
Set @SQL='Update ##List(['+@LName+']) Select Score From Score Where Score.Student_ID=##List.Student_ID '
+'and Score.Lesson_ID='+Convert(VarChar(10),@Lesson_ID)
Exec(@SQL)
Set @I=@I+1
end
4、列出学生的成绩
Select * From ##List Order By [学号]
 
你可以通过第一个表动态地生成.
s: string
select lesson_id,lesson_name from dbo.lesson order by lesson_id
while not eof do
begin
s:='SUM(CASE lesson_id WHEN 1 THEN score ELSE 0 END) AS'+fieldbyname('lesson_name')+','
next;
end;
s :='SELECT student_id as 学号,
Max(student_name) as 姓名,'+s
+'FROM dbo.score,dbo.student where score.dbo.student_id=student.student_id '
+'GROUP BY student_id'
生成好后再执行这条语句就OK!

 
巡城浪子:
s: string
select lesson_id,lesson_name from dbo.lesson order by lesson_id
while not eof do
begin
s := s + ',SUM(CASE lesson_id WHEN 1 THEN score ELSE 0 END) AS'+fieldbyname('lesson_name')
// 原句为:s := 'SUM(CASE lesson_id WHEN 1 THEN score ELSE 0 END) AS'+fieldbyname('lesson_name')+','

next;
end;
s :='SELECT student_id as 学号,
Max(student_name) as 姓名' + s
//原句为:Max(student_name) as 姓名,' + s
+'FROM dbo.score,dbo.student where score.dbo.student_id=student.student_id '
+'GROUP BY student_id'

 
select isnull(isnull(a.学号,b.学号),c.学号) as 学号,
isnull(isnull(a.姓名,b.姓名),c.姓名) as 姓名,
isnull(a.语文,0) as 语文,
isnull(a.数学,0) as 数学,
isnull(a.英语,0) as 英语,

from
(select student.student_id as 学号,student.name as 姓名,score.score as 语文 from lesson,student,score where score.lesson_id=lesson.lesson_id
and lesson.lesson_name="语文" group by student.student_id) a
full outer join
(select student.student_id as 学号,student.name as 姓名,score.score as 数学 from lesson,student,score where score.lesson_id=lesson.lesson_id
and lesson.lesson_name="数学" group by student.student_id) b
on a.学号=b.学号
full outer join
(select student.student_id as 学号,student.name as 姓名,score.score as 英语 from lesson,student,score where score.lesson_id=lesson.lesson_id
and lesson.lesson_name="英语" group by student.student_id) c
on a.学号=c.学号

有点恐怖!
 
各位,这是个交叉表查询的问题,在access中的语句是TRANSFORM,
TRANSFORM Max(score.score) AS score
SELECT score.student_id, Max(score.score) AS [小记]
FROM score
GROUP BY score.student_id
PIVOT score.lession_id;
在sqlserver中,我没有找到类似的用法
 
很简单的交叉表查询问题:
SELECT student_id,a.lesson_id,score,lesson_name INTO #TempTable1
FROM score AS a,lesson AS b
WHERE a.lesson_id=b.lesson_id

SELECT a.student_id,a.lesson_id,score,lesson_name,student_name INTO #TempTable2
FROM #TempTable1 AS a,student AS b
WHERE a.student_id=b.student_id

SELECT student_id AS 学号,student_name AS 姓名,
SUM(CASE lesson_id WHEN 11 THEN score ELSE 0 END) AS 语文,
SUM(CASE lesson_id WHEN 12 THEN score ELSE 0 END) AS 英语,
SUM(CASE lesson_id WHEN 13 THEN score ELSE 0 END) AS 数学
FROM #TempTable2
GROUP BY student_id,student_name
ORDER BY 学号
以上在SQL SERVER 7.0中测试通过!
 
这个问题你用 视图处理 就非常简单!
 

To
guqs,
xie_p_f,
江维,
你们的方法锁定了语,数,英三门课程,如果课程是变化的就行不通了.

例如.(dbo.lesson)是这样的

课程编码 课程名称
----------- --------------------------------------------------
3211201 计算机原理
3211102 高等数学
3216104 微机维修
3212103 汇编语言
....... ......
....... ......
To TYZhang:
您的方法正是我所期待的,不过有个问题还需要请教.
小明和小张都是同一个班的同学,他们在不同的客户端先后查询成绩.那么在SQL Sever
上会不会产生两张相同的临时表?也就是如何防止有相同的临时表产生.
.....
if exists(select * from tempdb..sysobjects where name='##List') Drop Table ##List
......
这段代码是起这样的作用的吗?




 
To Minor:
上面的那句话,就是为了让不同的学生查询到不同的结果,比如一年级开了10门课,二
年级开了12门课,那么两个年级的学生查到的表的字段数是不一样的。
而对于同一班级的学生,查到的结果应该是一样的。在SQLServer中全局临时表只能是
唯一的,也就是说,系统根本不容许产生两个相同的全局临时表,为了达到这个要求,只有
在每个人进行查询时先删除临时表,然后重建临时表。这样就基本解决问题。
但是以上用法有一个缺陷,就是当两个人在两个终端,同时查询时,会因为临时表的冲突,
导致一个人查询失败,但是因为临时表查询在内存中进行,速度很快,基本上不会产生并发,
即使产生了并发,查询失败时,只要重新查询一次就可以了。
我OICQ号是:32377774,如有疑问,再联系。。
 
呵呵~~我作过异构数据库集成:把部分的源程序给你看看:
form8.query1.close;
form8.query1.sql.Clear;
form8.query1.SQL.Add('select distinct sellbill.顾客号,Dbo_sellbill2.顾客电话,Sellbill.顾客姓名,Sellbill."顾客性别(F/M)",Sellbill.售出商品号,Sellbill.售出数量,Sellbill.商品单价(元) FROM ":SELL1:sellbill" Sellbill,":sell2:dbo.sellbill2" Dbo_sellbill2');
注意;
用这个时不用在datasource这个属性中指定数据源;
 
其实就是一个简单的交叉表查询,SqlServer不提供交叉表查询的SQL语句,而有一个变通
的方法,正如guqs,江维 描述的那样。(可以在Sql7 Book Online 的索引中,输入
Cross-tab查出一个详细的说明)

对于,科目不确定的问题,可以这么想
在执行这个查询之前,肯定能从科目表中得到具体的科目数量(可以有任意个)
那就根据这些科目名称动态的生成一个Cross-tab的查询语句。
 
用存储过程
先对课程表与学生表进行交叉联接生成一个临时表#表1
对#表1和成绩表进行左联接生成一个临时表#表2
对#表2进行交叉表查询。
就没问题。我要走了,来不及了。存储过程中间的详细内容回头告知:)
 
先生成临时表,再进行叉查询。
 
多人接受答案了。
 
后退
顶部