【SQL重溫】面試之數據庫基礎練習


簡介

最近在練習SQL基礎,首先感嘆一下,在機器上寫和在紙上寫還是有區別的。

本文的練習題目請點擊此鏈接進行查看:http://www.cnblogs.com/edisonchou/p/3878135.html


提要:本文只列舉個人認為有點難度,且有必須要重溫知識點的題目,詳細還請查看上面所給的鏈接進行練習。

練習題

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

  1. 思路1:使用++intersect++(intersect的使用
  2. 思路1:使用++EXISTS++(EXISTS的用法
--解法一:求交集
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與IN的使用效率的問題,通常情況下采用exists要比in效率高,因為IN不走索引,但要看實際情況具體使用:
IN適合於外表大而內表小的情況;EXISTS適合於外表小而內表大的情況。

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

分析:這題要注意一個老師可能教多門課

  1. 先在成績單上查詢到教師為“葉平”老師的信息,通過學生ID進行分組並獲取考試門數
  2. 然后統計課程表上的“葉平”老師的課程數
    3.第一個條件的學生考試門數跟第二個條件的“葉平”老師所教課程數進行對比,相等即時答案
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='葉平'
    )
)

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

注意:查詢的是跟“002”完全相同,且是其他,記得得排除“002”

  1. 首先確定學生課程范圍在“002”學生所選的課程范圍內;
  2. 然后就是對比他們間的課程數。

完成上面兩個條件即可確定他們所選的所有課程是否都相等了

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'
    )
)

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

  1. 先查詢第一個條件的學員,因為插入的學號需要用到;
  2. 然后獲取課程“002”的平均分,這里是獲取分數用於插入;

最后答案就順理成章了:

INSERT INTO dbo.Sc
SELECT s.S#,'002',(SELECT AVG(score) FROM dbo.Sc WHERE C#='002')
from  dbo.Student s
WHERE s.S# NOT IN(SELECT DISTINCT(sc.S#) FROM dbo.Sc sc WHERE sc.C#='002')
 

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

這里涉及到行轉列的知識,在查詢語數英這三列的時候用到了子查詢和主查詢的關聯保證了與其他列數據的關聯性

  1. 請各位要注意對分組(Group by)的概念較為清晰,重點就在學生的ID:S#
  2. 行轉列知識:http://www.cnblogs.com/kerrycode/archive/2010/07/28/1786547.html
select t.S# as '學生ID',
(select Score from SC where S#=t.S# and C#='002') as '語文',
(select Score from SC where S#=t.S# and C#='003') as '數學',
(select Score from SC where S#=t.S# and C#='004') as '英語',
COUNT(t.C#) as '有效課程數',
AVG(t.Score) as '有效平均分'
from SC t
group by t.S#
order by AVG(t.Score)

(19)按各科平均成績從低到高和及格率的百分數從高到低順序

  1. CASE WHEN *** THEN *** ELSE *** END 的使用
  2. 及格率SUM(PassedCounts)/COUNT(AllCounts)的計算
  3. 另外,這里[Percent(%)]可以使用100 * SUM(CASE WHEN ISNULL(sc.Score,0)>=60 THEN 1 ELSE 0 END)/COUNT(*)替代。
 SELECT sc.C#,c.Cname,AVG(sc.score) AS avgScore,100*SUM(CASE WHEN ISNULL(score,0)>=60 THEN 1 ELSE 0 END )/COUNT(*) 
 FROM dbo.Sc sc,dbo.Course c
 WHERE sc.C#=c.C#
 GROUP BY sc.C#,c.Cname
 order BY AVG(sc.score)

(20)查詢如下課程平均成績和及格率的百分數(備注:需要在1行內顯示): 企業管理(002),OO&UML (003),數據庫(004)

這里也是涉及行轉列的問題,由於列的數據都是相對獨立的,也就沒有關聯子查詢的的問題了

select 
SUM(CASE WHEN C#='002' THEN Score ELSE 0 END)/SUM(CASE C# WHEN '002' THEN 1 ELSE 0 END) as '企業管理平均分',
100 * SUM(CASE WHEN C#='002' and Score>=60 THEN 1 ELSE 0 END)/SUM(CASE C# WHEN '002' THEN 1 ELSE 0 END) as '企業管理及格百分比',
SUM(CASE WHEN C#='003' THEN Score ELSE 0 END)/SUM(CASE C# WHEN '003' THEN 1 ELSE 0 END) as 'OO&UML平均分',
100 * SUM(CASE WHEN C#='003' and Score>=60 THEN 1 ELSE 0 END)/SUM(CASE C# WHEN '003' THEN 1 ELSE 0 END) as 'OO&UML及格百分比',
SUM(CASE WHEN C#='004' THEN Score ELSE 0 END)/SUM(CASE C# WHEN '004' THEN 1 ELSE 0 END) as '數據庫平均分',
100 * SUM(CASE WHEN C#='004' and Score>=60 THEN 1 ELSE 0 END)/SUM(CASE C# WHEN '004' THEN 1 ELSE 0 END) as '數據庫及格百分比'
from SC

(24)查詢學生平均成績及其名次;

看似簡單,名次這里其實不好弄。

  1. 首先使用group by獲取需要的字段(學生ID,平均分)
  2. 然后這段sql需要再拿來新建並進行對比
select s.S#,s.Sname,T2.AvgScore,
    (select COUNT(AvgScore) from 
    (select S#,AVG(Score) as 'AvgScore' from SC group by S#) as T1 
    where T2.AvgScore<T1.AvgScore)+1 as 'Rank'
from 
    (select S#,AVG(Score) as 'AvgScore' from SC
    group by S#) as T2,
    Student s
where s.S#=T2.S#
order by AvgScore desc

(25)查詢各科成績前三名的記錄:(不考慮成績並列情況)

  1. 建立子查詢獲取每科前三名,這里需要跟主查詢進行關聯,而關聯的字段就是科目字段C#
  2. 主查詢難度不大,查詢條件包括分數區域在子查詢的分數區域內並且主和子查詢的科目進行關聯
select sc.C#,c.Cname,sc.S#,s.Sname,sc.Score 
from Student s,SC sc,Course c
where sc.C#=c.C# and sc.S#=s.S# and sc.Score in
(
    select top 3 Score from SC sc2
    where sc.C#=sc2.C#
    Order by Score desc
)
order by sc.C#,sc.Score desc

以上就是我用紙張手寫的時候遇到有難度的題目,希望能給各位一些參考。


免責聲明!

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



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