SQL Server 基礎之《學生表-教師表-課程表-選課表》(一)


數據庫表結構及數據

建表

 1 CREATE TABLE Student 
 2   ( 
 3      S#    INT, 
 4      Sname nvarchar(32), 
 5      Sage  INT, 
 6      Ssex  nvarchar(8) 
 7   ) 
 8 
 9 CREATE TABLE Course 
10   ( 
11      C#    INT, 
12      Cname nvarchar(32), 
13      T#    INT 
14   ) 
15 
16 CREATE TABLE Sc 
17   ( 
18      S#    INT, 
19      C#    INT, 
20      score INT 
21   ) 
22 
23 CREATE TABLE Teacher 
24   ( 
25      T#    INT, 
26      Tname nvarchar(16) 
27   )
View Code

測試數據

 1 insert into Student select 1,N'劉一',18,N'' union all
 2  select 2,N'錢二',19,N'' union all
 3  select 3,N'張三',17,N'' union all
 4  select 4,N'李四',18,N'' union all
 5  select 5,N'王五',17,N'' union all
 6  select 6,N'趙六',19,N'' 
 7  
 8  insert into Teacher select 1,N'葉平' union all
 9  select 2,N'賀高' union all
10  select 3,N'楊艷' union all
11  select 4,N'周磊'
12  
13  insert into Course select 1,N'語文',1 union all
14  select 2,N'數學',2 union all
15  select 3,N'英語',3 union all
16  select 4,N'物理',4
17  
18  insert into SC 
19  select 1,1,56 union all 
20  select 1,2,78 union all 
21  select 1,3,67 union all 
22  select 1,4,58 union all 
23  select 2,1,79 union all 
24  select 2,2,81 union all 
25  select 2,3,92 union all 
26  select 2,4,68 union all 
27  select 3,1,91 union all 
28  select 3,2,47 union all 
29  select 3,3,88 union all 
30  select 3,4,56 union all 
31  select 4,2,88 union all 
32  select 4,3,90 union all 
33  select 4,4,93 union all 
34  select 5,1,46 union all 
35  select 5,3,78 union all 
36  select 5,4,53 union all 
37  select 6,1,35 union all 
38  select 6,2,68 union all 
39  select 6,4,71
View Code

數據庫多表查詢之 where & INNER JOIN

在多表查詢中,一些SQL開發人員更喜歡使用WHERE來做join,比如:

SELECT a.ID, b.Name, b.Date FROM Customers a, Sales b WHERE a.ID = b.ID;

  WHERE子句中使用的連接語句,在數據庫語言中,被稱為隱性連接。INNER JOIN……ON子句產生的連接稱為顯性連接。(其他JOIN參數也是顯性連接)WHERE 和INNER JOIN產生的連接關系,沒有本質區別,結果也一樣。但是!隱性連接隨着數據庫語言的規范和發展,已經逐漸被淘汰,比較新的數據庫語言基本上已經拋棄了隱性連接,全部采用顯性連接了。

  缺點:在上面語句中,實際上是創建了兩張表的笛卡爾積,所有可能的組合都會被創建出來。在笛卡爾連接中,在上面的例子中,如果有1000顧客和1000條銷售記錄,這個查詢會先產生1000000個結果,然后通過正確的 ID過濾出1000條記錄。 這是一種低效利用數據庫資源,數據庫多做100倍的工作。 在大型數據庫中,笛卡爾連接是一個大問題,對兩個大表的笛卡爾積會創建數10億或萬億的記錄。

為了避免創建笛卡爾積,應該使用INNER JOIN :

SELECT a.ID, b.Name, b.Date FROM Customers a INNER JOIN Sales b ON a.ID = b.ID;

  優點:如上面語句,使用inner join 這樣數據庫就只產生等於ID 的1000條目標結果。增加了查詢效率。

練習題目

1.查詢“001”課程比“002”課程成績高的所有學生的學號;

select * from
(select S#,Score from SC where C#='001') a,
(select S#,Score from SC where C#='002') b
where a.S#=b.S# and a.Score>b.Score

       

2.查詢平均成績大於60分的同學的學號和平均成績;
方法一:

select * from
(select S#,AVG(score) as av from sc 
group by S# ) S
where S.av>60

方法二:

select S#,AVG(Score) as AvgScore 
from SC
group by S#
having AVG(Score)>60

      

3.查詢所有同學的學號、姓名、選課數、總成績;

select S.S#,S.Sname,COUNT(C#) as CourseCount, SUM(score) as ScoreSum 
from Student as S left join Sc as C 
on S.S#=C.S#
group by S.S#,S.Sname
order by S.S#

       

4.查詢姓“李”的老師的個數;

select count(distinct Tname) as count from Teacher where Tname like '李%'

      

5.查詢沒學過“葉平”老師課的同學的學號、姓名;

select S.S#,S.Sname 
from Student as S 
where S.S# not in 
(select distinct(sc.S#) from SC sc,Course c,Teacher t where sc.C#=c.C# and c.T#=t.T# and t.Tname='葉平') 

      

 6.查詢學過“001”並且也學過編號“002”課程的同學的學號、姓名;

--解法一:求交集
select s.S#,s.Sname
from Student s,SC sc
where s.S#=sc.S# and sc.C#='001'
intersect
select s.S#,s.Sname
from Student s,SC sc
where s.S#=sc.S# and sc.C#='002'
--解法二:使用exists
select s.S#,s.Sname
from Student s,SC sc
where s.S#=sc.S# and sc.C#='001' and exists
(
    select * from SC sc2 where sc.S#=sc2.S# and sc2.C#='002'
)

EXISTS用於檢查子查詢是否至少會返回一行數據,該子查詢實際上並不返回任何數據,而是返回值True或False。那么,這里我們來看一下in和exists的區別

  ①in 是把外表和內表作hash 連接,而exists是對外表作loop循環,每次loop循環再對內表進行查詢。

  ②一直以來認為exists比in效率高的說法是不准確的

 -->如果查詢的兩個表大小相當,那么用in和exists差別不大。

 -->如果兩個表中一個較小,一個是大表,則子查詢表大的用exists,子查詢表小的用in。

(7)查詢學過“葉平”老師所教的所有課的同學的學號、姓名;

--方法一
select s.S#,s.Sname 
from Student s
where s.S# in 
(
  select S# from Sc sc where sc.C# in 
  (
    select C# from Teacher t 
    inner join Course c on t.T#=c.T#
    where t.Tname='葉平'
  )
)
--方法二
select s.S#,s.Sname 
from Student s
where s.S# in 
(
    select sc.S# 
    from SC sc,Course c,Teacher t
    where c.C#=sc.C# and c.T#=t.T# and t.Tname='葉平'
    group by sc.S#
    having COUNT(sc.C#)=
    (
        select COUNT(c1.C#) 
        from Course c1,Teacher t1 
        where c1.T#=t1.T# and t1.Tname='葉平'
    )
)

(8)查詢課程編號“002”的成績比課程編號“001”課程低的所有同學的學號、姓名;

  select s.S#,s.Sname from Student s,
  (select sc1.S#,sc1.Score from SC sc1 where sc1.C#='002') a,
  (select sc2.S#,sc2.Score from SC sc2 where sc2.C#='001') b
   where s.S#=a.S# and s.S#=b.S# and a.S#=b.S# and a.Score<b.Score

(9)查詢有課程成績小於60分的同學的學號、姓名;

 

  select s.S#,s.Sname
  from dbo.Student s
  left join dbo.Sc sc 
  on s.S#=sc.S#
  where sc.score < 60
  group by s.S#,s.Sname

 

select s.S#,s.Sname 
from Student s
where s.S# in
(
    select distinct(sc.S#) from SC sc
    where s.S#=sc.S# and sc.Score<60
)

(10)查詢沒有學全所有課的同學的學號、姓名;(可以從學全的學生中取反)

select s.S#,s.Sname
from Student s
where s.S# not in
(
    select sc.S#  from SC sc
    group by sc.S#
    having COUNT(distinct sc.C#)= --按照學號分組計算每個學號總的課程數
    (
        select COUNT(distinct c.C#) from Course c --計算總得課程數
    )
)

(11)查詢至少有一門課與學號為“001”的同學所學相同的同學的學號和姓名;

--方法一
select s.S#,s.Sname from dbo.Student s
where s.S# in
  (
    select distinct(sc.S#) from dbo.Sc where sc.C# 
    in(select  distinct(sc.C#)  from dbo.Sc sc where sc.S# = '001')
  )
--方法二
select distinct(s.S#),s.Sname from dbo.Student s
inner join dbo.Sc 
on s.S# =sc.S# and s.S# in
  (
    select distinct(sc.S#) from dbo.Sc where sc.C# 
    in(select  distinct(sc.C#)  from dbo.Sc sc where sc.S# = '001')
  )
--方法三
 select distinct(s.S#),s.Sname
from Student s,SC sc
where s.S#=sc.S# and sc.C# in
(
    select distinct(sc2.C#) from SC sc2
    where sc2.S#='001'
)
order by s.S# asc

 (12)查詢至少學過學號為“001”同學所有一門課的其他同學學號和姓名;(感覺跟11題有重疊)

select distinct(s.S#),s.Sname 
from Student s,SC sc
where s.S#=sc.S# and s.S#!='001' and sc.C# in
(
    select distinct(sc2.C#) from SC sc2
    where sc2.S#='001'
)
order by s.S# asc

(13)把“SC”表中“葉平”老師教的課的成績都更改為此課程的平均成績;

update SC set Score=
(
    select AVG(score) from SC sc,Course c,Teacher t
    where sc.C#=c.C# and c.T#=t.T# and t.Tname='葉平' 
)
where C# in 
(
    select distinct(sc.C#) from SC sc,Course c,Teacher t
    where sc.C#=c.C# and c.T#=t.T# and t.Tname='葉平'
)

查詢“葉平”老師教的課

select * from dbo.Sc sc where sc.C# in
(
    select c.C# from dbo.Teacher t 
    inner join dbo.Course c
    on t.T#= c.T# 
    where t.Tname='葉平' 
)

 

 --(14)查詢和“002”號的同學學習的課程完全相同的其他同學學號和姓名;

select s.S#,s.Sname 
from Student s
where s.S#!='002' and s.S# in 
(
    select distinct(S#) from SC
    where C# in (select C# from SC where S#='002')
    group by S#
    having COUNT(distinct C#)=
    (
        select COUNT(distinct C#) from SC
        where S#='002'
    )
)

(15)刪除學習“葉平”老師課的SC表記錄;

delete from SC where C# in
(
    select c.C# from Course c,Teacher t
    where c.T#=t.T# and t.Tname='葉平'
)

(16)向SC表中插入一些記錄,這些記錄要求符合以下條件:①沒有上過編號“002”課程的同學學號;②插入“002”號課程的平均成績; 

  insert into SC
  select s.S#,'002' C#,(select AVG(sc.score) from dbo.Sc sc where sc.C# = '002') score
   from dbo.Student s where s.S# not in
  (
    select distinct(sc.S#)  from dbo.Sc sc where sc.C# ='002'
  )

(17)按平均成績從低到高顯示所有學生的“語文”、“數學”、“英語”三門的課程成績,按如下形式顯示: 學生ID,語文,數學,英語,有效課程數,有效平均分;

select t.S# as '學生ID',
(select Score from SC sc where sc.S#=t.S# and sc.C#='002') as '語文',
(select Score from SC sc where sc.S#=t.S# and sc.C#='003') as '數學',
(select Score from SC sc where sc.S#=t.S# and sc.C#='004') as '英語',
COUNT(t.C#) as '有效課程數',
AVG(t.Score) as '有效平均分'
from SC t
group by t.S#
order by AVG(t.Score)

sql中自連接的使用

select sc2.S# as '學生ID',
(select Score from SC sc1 where sc1.S#=sc2.S# and sc1.C#='002') as '語文'
from SC sc2
group by sc2.S#

資料

sql面試題(學生表_課程表_成績表_教師表)

http://www.cnblogs.com/edisonchou/p/3878135.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM