數據庫表結構及數據


建表
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 )
測試數據
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
數據庫多表查詢之 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#

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