你必知必會的SQL面試題


寫在前面的話

本文參考原博《 走向面試之數據庫基礎:一、你必知必會的SQL語句練習-Part 1》和《 走向面試之數據庫基礎:一、你必知必會的SQL語句練習-Part 2》進行練習,部分題目在不變化其練習目的的情況下進行了題意改動,並刪除部分重復和無表的題目。

在此之前已練習完兩遍並分別放在WizNote和Github,其中第二遍在Github上針對個人的sql弱項題目進行了更詳細的說明( Github:MyTraining/sql),隨着越來越熟練,本文作為第三次練習,部分重點題目的詳細解析和想法在這里就沒有具體描述,或許以后會補上,但是誰知道呢(攤手)。

涉及的表結構和測試數據

使用數據庫軟件直接導出的SQL(偷懶直接把Part1和Part2的導在一起的,因為表名各不相同所以這里並不影響練習使用),數據庫是MySQL。


Part 1 練習題和參考解

(1)查詢“001”課程比“002”課程成績低的所有學生的學號、001學科成績、002學科成績
SELECT 
  s1.StudentNo,
  s1.score AS '001',
  s2.score AS '002'
FROM
  score s1,
  (
  SELECT
    *
  FROM
    score s
  WHERE
    s.CourseNo = 2
  ) s2
WHERE
  s1.CourseNo = 1
  AND
  s1.StudentNo = s2.StudentNo
  AND
  s1.score < s2.score
  ORDER BY s1.StudentNo

SELECT
  s1.StudentNo,
  s1.score AS '001',
  s2.score AS '002'
FROM 
  score s1, 
  score s2
WHERE 
  s1.CourseNo = 001 
  AND 
  s2.CourseNo = 002 
  AND 
  s1.StudentNo = s2.StudentNo
  AND
  s1.score < s2.score
  ORDER BY s1.StudentNo


(2)查詢平均成績大於60分的同學的學號和平均成績

SELECT
  s1.StudentNo,
  AVG(s1.score)
FROM
  score s1
GROUP BY s1.StudentNo
HAVING AVG(s1.score)>60


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

SELECT
  s1.StudentNo,
  stu1.name,
  COUNT(*),
  SUM(s1.score)
FROM
  score s1,
  student stu1
WHERE
  s1.StudentNo = stu1.StudentNo
GROUP BY s1.StudentNo


(4)查詢姓“李”的老師的個數

SELECT
  COUNT(*)
FROM
  teacher t1
WHERE
  t1.name like '李%'


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

SELECT
  stu1.StudentNo,
  stu1.name
FROM
  student stu1
WHERE
  stu1.StudentNo NOT IN
  (
  SELECT DISTINCT
    s1.StudentNo
  FROM
    score s1,
    course c1,
    teacher t1
  WHERE
    s1.courseNo = c1.CourseNo
    AND
    c1.teacherNo = t1.teacherNo
    AND
    t1.name = '葉平'
  )

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

-- 這個算法比普通的要有想法
SELECT
  s1.StudentNo,
  stu1.name
FROM
  score s1,
  student stu1
WHERE
  s1.StudentNo = stu1.StudentNo
  AND
  s1.CourseNo IN (1, 2)
GROUP BY s1.StudentNo
HAVING COUNT(*) = 2

SELECT
  s1.StudentNo,
  stu1.name
FROM
  score s1,
  student stu1
WHERE
  s1.StudentNo = stu1.StudentNo
  AND
  s1.CourseNo = 1
  AND
  s1.StudentNo IN
  (
  SELECT
    s2.StudentNo
  FROM
    score s2
  WHERE
    s2.CourseNo = 2
  )

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

-- 利用主鍵值不相同,它們的和一定各不相同,葉平老師的課程的主鍵值和如果與學生所學的葉平老師的課程的主鍵值和相等,那么說明學了葉平老師所有課程
SELECT
  stu1.StudentNo,
  stu1.name
FROM
  score s1,
  student stu1,
  course c1,
  teacher t1
WHERE
  s1.StudentNo = stu1.StudentNo
  AND
  s1.CourseNo = c1.CourseNo
  AND
  c1.teacherNo = t1.teacherNo
  AND
  t1.name = '葉平'
GROUP BY s1.StudentNo
HAVING SUM(s1.CourseNo)=
(
SELECT
  SUM(c2.CourseNo)
FROM
  course c2,
  teacher t2
WHERE
  c2.teacherNo = t2.teacherNo
  AND
  t2.name = '葉平'
)

-- 如果學生學習葉平老師的課程數量,與葉平老師所教學課程的數量相同,那么說明該同學學了葉平老師的所有課程
SELECT
  stu1.StudentNo,
  stu1.name
FROM
  score s1,
  student stu1,
  course c1,
  teacher t1
WHERE
  s1.StudentNo = stu1.StudentNo
  AND
  s1.CourseNo = c1.CourseNo
  AND
  c1.teacherNo = t1.teacherNo
  AND
  t1.name = '葉平'
GROUP BY s1.StudentNo
HAVING COUNT(*) =
(
SELECT
  COUNT(*)
FROM
  course c2,
  teacher t2
WHERE
  c2.teacherNo = t2.teacherNo
  AND
  t2.name = '葉平' 
)

(8)查詢課程編號“002”的成績比課程編號“001”課程低的所有同學的學號、姓名
SELECT
  stu1.studentNo,
  stu1.name
FROM
  score s1,
  (
  SELECT
    s2.StudentNo,
    s2.score
  FROM
    score s2
  WHERE
    s2.CourseNo = 1
  ) t2,
  student stu1
WHERE
  s1.CourseNo = 2
  AND 
  s1.StudentNo = t2.StudentNo
  AND 
  s1.score < t2.score
  AND 
  s1.StudentNo = stu1.studentNo

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

SELECT DISTINCT
  s1.StudentNo,
  stu1.name
FROM
  score s1,
  student stu1
WHERE
  s1.StudentNo = stu1.studentNo
  AND
  s1.score < 60

(10)查詢沒有學全所有課的同學的學號、姓名

SELECT
  stu1.StudentNo,
  stu1.name
FROM
  score s1,
  student stu1
WHERE
  s1.StudentNo = stu1.StudentNo
GROUP BY s1.StudentNo
HAVING COUNT(*) < 
(
SELECT
  COUNT(*)
FROM
  course c1
)

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

SELECT DISTINCT
  stu1.StudentNo,
  stu1.name
FROM
  score s1,
  student stu1
WHERE
  s1.StudentNo = stu1.StudentNo
  AND
  s1.CourseNo IN
  (
  SELECT
    s2.CourseNo
  FROM
    score s2
  WHERE
    s2.StudentNo = 1
  )

(12)查詢至少學過學號為“001”同學所有一門課的其他同學學號和姓名(和11題撞臉,排除1號同學就可以了)

SELECT DISTINCT
  stu1.StudentNo,
  stu1.name
FROM
  score s1,
  student stu1
WHERE
  s1.StudentNo = stu1.StudentNo
  AND
  s1.StudentNo != 1
  AND
  s1.CourseNo IN
  (
  SELECT
    s2.CourseNo
  FROM
    score s2
  WHERE
    s2.StudentNo = 1
  )

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

-- 涉及將兩表聯合,將本表某字段的值按條件設置為另個表的某個字段的值 (參考鏈接:MySQL:把一個表中的數據按鍵值更新(update)到另一個表)
UPDATE
  score s,
  (
  SELECT
    s1.CourseNo as courseNo,
    AVG(s1.score) as avgScore 
  FROM
    score s1,
    course c1,
    teacher t1
  WHERE
    s1.CourseNo = c1.CourseNo
    AND
    c1.teacherNo = t1.teacherNo
    AND
    t1.name = '葉平'
  GROUP BY s1.CourseNo
  ) as t
SET
  s.score = t.avgScore
WHERE
  s.CourseNo = t.courseNo

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

SELECT
  stu.studentNo,
  stu.name
FROM
  score s,
  student stu
WHERE
  s.StudentNo != 2
  AND
  s.StudentNo = stu.studentNo
GROUP BY s.StudentNo
HAVING SUM(s.CourseNo)=
(
SELECT
  SUM(s1.CourseNo)
FROM
  score s1
WHERE
  s1.StudentNo = 2
)

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

DELETE FROM
  score s
WHERE
  s.CourseNo IN
  (
  SELECT
    c.CourseNo
  FROM
    course c,
    teacher t
  WHERE
    c.teacherNo = t.teacherNo
    AND
    t.name = '葉平'
  )

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

-- 本題采用插入子查詢的方式,三個字段中后兩個字段為常量(基本格式:INSERT INTO R(A1, A2 ... ,An) 子查詢)
INSERT INTO
  score(StudentNo, CourseNo, score)
(
SELECT 
  stu.studentNo,
  2,
  (SELECT AVG(s3.score) FROM score s3 WHERE s3.CourseNo = 2)
FROM 
  student stu 
WHERE 
  stu.studentNo 
NOT IN 
(
SELECT 
  s2.StudentNo 
FROM 
  score s2 
WHERE 
  s2.CourseNo = 2
)
)

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

-- 用了個極蠢的辦法,雖然很瓜很繞但是也算是溫習了下相關子查詢、CASE WHEN、EXISTS了,另外對自己也有所啟發,就留下了
-- 然后做到這里的時候感慨,隨着練習總是越來越熟練的,盡管自己寫得很繞,但以往是根本想不到用什么CASE WHEN、EXISTS之類的,也算是成長吧
SELECT
  stu.studentNo,
  CASE WHEN EXISTS (SELECT * FROM score s1 WHERE s1.CourseNo = 1 AND s1.studentNo = stu.studentNo) THEN (SELECT s.score FROM score s WHERE s.CourseNo = 1 AND s.studentNo = stu.studentNo) ELSE NULL END AS "語文",
  CASE WHEN EXISTS (SELECT * FROM score s2 WHERE s2.CourseNo = 2 AND s2.studentNo = stu.studentNo) THEN (SELECT s.score FROM score s WHERE s.CourseNo = 2 AND s.studentNo = stu.studentNo) ELSE NULL END AS "數學",
  CASE WHEN EXISTS (SELECT * FROM score s3 WHERE s3.CourseNo = 3 AND s3.studentNo = stu.studentNo) THEN (SELECT s.score FROM score s WHERE s.CourseNo = 3 AND s.studentNo = stu.studentNo) ELSE NULL END AS "英語",
  t1.validateCount AS '有效科目數',
  t2.validateAVG AS '有效平均分'
FROM
  student stu,
  (SELECT s.studentNo, COUNT(*) AS validateCount FROM score s WHERE s.CourseNo IN (1, 2, 3) GROUP BY s.StudentNo) as t1,
  (SELECT s.studentNo, AVG(s.score) AS validateAVG FROM score s WHERE s.CourseNo IN (1, 2, 3) GROUP BY s.StudentNo) as t2
WHERE
  stu.studentNo = t1.studentNo
  AND
  stu.studentNo = t2.studentNo
ORDER BY stu.StudentNo

-- 另外,參考博客中博主給出的答案如下,比我的就簡潔多了,
-- 其次,他在這里的有效課程數和有效平均分是針對學生所有的成績,而並非此處的僅僅三科
-- 因為題意也不是很清楚,也就作罷,正好算是兩種形式吧
SELECT
  s.StudentNo,
  (SELECT s1.score FROM score s1 WHERE s1.CourseNo=1 AND s1.StudentNo = s.StudentNo) AS "語文",
  (SELECT s2.score FROM score s2 WHERE s2.CourseNo=2 AND s2.StudentNo = s.StudentNo) AS "數學",
  (SELECT s3.score FROM score s3 WHERE s3.CourseNo=3 AND s3.StudentNo = s.StudentNo) AS "英語",
  COUNT(s.CourseNo) AS "有效課程數",
  AVG(s.score) AS "有效平均分"
FROM
  score s
GROUP BY s.StudentNo
ORDER BY s.StudentNo

(18)查詢各科成績最高和最低的分:以如下形式顯示:課程ID,最高分,最低分;

SELECT
  s.CourseNo,
  MAX(s.score),
  MIN(s.score)
FROM
  score s
GROUP BY
  s.CourseNo

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

-- 看了下上次在Github上寫的,不得不說,practice makes perfect
SELECT
  s.CourseNo,
  c.name,
  AVG(s.score) AS '平均分',
  SUM(CASE WHEN s.score > 60 THEN 1 ELSE 0 END) AS '及格數',
  COUNT(*) AS '總數',
  SUM(CASE WHEN s.score > 60 THEN 1 ELSE 0 END)/COUNT(*)*100 AS '及格率'
FROM
  score s,
  course c
WHERE
  s.CourseNo = c.courseNo
GROUP BY s.CourseNo
ORDER BY AVG(s.score), SUM(CASE WHEN s.score > 60 THEN 1 ELSE 0 END)/COUNT(*) DESC

還不完全,參考原博主,加isnull

(20)查詢不同老師所教不同課程平均分從高到低顯示

SELECT
  c1.name,
  t1.name,
  AVG(s1.score)
FROM
  score s1,
  course c1,
  teacher t1
WHERE
  s1.CourseNo = c1.courseNo
  AND
  c1.teacherNo = t1.teacherNo
GROUP BY s1.CourseNo
ORDER BY AVG(s1.score) DESC

(21)統計列印各科成績,各分數段人數:課程ID,課程名稱,(100-85),(85-70,(70-60),( 低於60)

SELECT
  c.courseNo AS '課程ID',
  c.name AS '課程名稱',
  SUM(CASE WHEN s.score BETWEEN 85 AND 100 THEN 1 ELSE 0 END) AS '(100-85)',
  SUM(CASE WHEN s.score BETWEEN 70 AND 85 THEN 1 ELSE 0 END) AS '(85-70)',
  SUM(CASE WHEN s.score BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS '(70-60)',
  SUM(CASE WHEN s.score < 60 THEN 1 ELSE 0 END) AS '(低於60)'
FROM
  course c,
  score s
WHERE
  c.courseNo = s.CourseNo
GROUP BY c.courseNo

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

SELECT
	*
FROM
  score s
WHERE
  (
	SELECT
		COUNT(*)
	FROM
		score s1
	WHERE
		s1.CourseNo = s.CourseNo
		AND
		s1.score > s.score
	) < 3
ORDER BY s.CourseNo

(23)查詢每門課程被選修的學生數

SELECT
  c.name AS '課程',
  COUNT(s.StudentNo) AS '選修學生數'
FROM
  course c LEFT JOIN score s ON c.courseNo = s.CourseNo
GROUP BY c.courseNo

(24)查詢出只選修了一門課程的全部學生的學號和姓名

SELECT
  stu1.StudentNo AS '學號',
	stu1.name AS '姓名'
FROM
  (SELECT StudentNo, COUNT(CourseNo) AS amount FROM score GROUP BY StudentNo) t1,
  student stu1
WHERE
  t1.StudentNo = stu1.studentNo
  AND
  t1.amount = 1

SELECT
  stu1.studentNo AS '學號',
  stu1.name AS '姓名'
FROM
  score s,
  student stu1
WHERE
  s.StudentNo = stu1.studentNo
GROUP BY s.StudentNo
HAVING COUNT(s.CourseNo) = 1

(25)查詢男生、女生的人數

SELECT
  s.sex AS '性別',
  COUNT(*) AS '人數'
FROM
  student s
GROUP BY s.sex

(26)查詢同名同姓學生名單,並統計同名人數

SELECT
  s.name AS '姓名',
  COUNT(*) AS '學生數'
FROM
  student s
GROUP BY s.name

(27)查詢1991年出生的學生名單

SELECT
  s.name AS '姓名'
FROM
  student s
WHERE
  YEAR(CURDATE()) - s.age = 1991

(28)查詢每門課程的平均成績,結果按平均成績升序排列

#未考慮到課程無人選修的情況
SELECT
  c.name AS '課程名稱',
  AVG(s.score) AS '平均成績'
FROM
  score s,
  course c
WHERE
  s.CourseNo = c.courseNo
GROUP BY c.courseNo
ORDER BY AVG(s.score)



#如果某課程無人選修,其平均成績顯示為null
SELECT
  c.name AS '課程名稱',
  AVG(s.score) AS '平均成績'
FROM
  course c LEFT JOIN score s ON c.courseNo = s.CourseNo
GROUP BY c.courseNo  
ORDER BY AVG(s.score)

(29)查詢平均成績大於85的所有學生的學號、姓名和平均成績

SELECT
  stu.studentNo AS '學號',
  stu.name AS '姓名',
  AVG(s.score) AS '平均成績'
FROM
  score s,
  student stu
WHERE
  s.StudentNo = stu.studentNo
GROUP BY s.StudentNo
HAVING AVG(s.score) > 85

(30)查詢課程名稱為“數學”,且分數低於60的學生姓名和分數

SELECT
  stu.name AS '姓名',
  s.score AS '數學成績'
FROM
  score s,
  course c,
  student stu
WHERE
  s.CourseNo = c.courseNo
  AND
  s.StudentNo = stu.studentNo
  AND
  c.name = '數學'
  AND
  s.score < 60

(31)查詢所有學生的選課情況

SELECT
  stu.name AS '姓名',
  c.name AS '選課'
FROM
  score s,
  course c,
  student stu
WHERE
  s.CourseNo = c.courseNo
  AND
  s.StudentNo = stu.studentNo
ORDER BY stu.name

(32)查詢任何一門課程成績在70分以上的姓名、課程名稱和分數

SELECT
  stu.name AS '姓名',
  c.name AS '課程名稱',
  s.score AS '分數'
FROM
  score s,
  student stu,
  course c
WHERE
  s.StudentNo = stu.studentNo
  AND
  s.CourseNo = c.courseNo
  AND
  s.score > 70

(33)查詢不及格的課程,並按課程號從大到小排列

#包含不及格記錄的課程
SELECT DISTINCT
  c.courseNo AS '課程號',
  c.name AS '課程名稱' 
FROM
  score s,
  course c
WHERE
  s.CourseNo = c.courseNo
  AND
  s.score < 60

#不及格的課程的選修記錄
SELECT
  stu.name AS '姓名',
  c.name AS '課程名稱',
  s.score AS '分數'
FROM
  score s,
  student stu,
  course c
WHERE
  s.StudentNo = stu.studentNo
  AND
  s.CourseNo = c.courseNo
  AND
  s.score < 60
ORDER BY c.courseNo DESC

(34) 查詢課程編號為003且課程成績在80分以上的學生的學號和姓名

SELECT
  stu.studentNo AS '學號',
  stu.name AS '姓名'
FROM
  score s,
  student stu
WHERE
  s.StudentNo = stu.studentNo
  AND
  s.CourseNo = 3
  AND
  s.score > 80

(35)求選了課程的學生人數

#method-1
SELECT
  COUNT(DISTINCT s.StudentNo) AS '選了課程的學生人數'
FROM
  score s

#method-2
SELECT
  COUNT(*) AS '選了課程的學生人數'
FROM
  (SELECT * FROM score s GROUP BY s.StudentNo) t

(36)查詢選修“楊艷”老師所授課程的學生中,成績最高的學生姓名及其成績

SELECT
  stu.name AS '學生姓名',
  s.score AS '成績'
FROM
  score s,
  student stu,
  course c,
  teacher t
WHERE
  s.StudentNo = stu.studentNo
  AND
  s.CourseNo = c.courseNo
  AND
  c.teacherNo = t.teacherNo
  AND
  t.name = '楊艷'
ORDER BY s.score DESC
LIMIT 0, 1

(37) 查詢各個課程及相應的選修人數

SELECT
  c.name AS '課程名稱',
  COUNT(*) AS '選修人數'
FROM
  score s,
  course c
WHERE
  s.CourseNo = c.courseNo
GROUP BY s.CourseNo

(38)查詢不同課程但成績相同的學生的學號、課程號、學生成績

#method-1
SELECT
  s.StudentNo AS '學號',
  s.CourseNo AS '課程號',
  s.score AS '成績'
FROM
  score s
WHERE
  (SELECT COUNT(*) FROM score s1 WHERE s1.score = s.score AND s1.CourseNo <> s.COurseNo) > 0
ORDER BY s.score DESC, s.StudentNo, s.CourseNo

#method-2
SELECT DISTINCT
  s1.StudentNo AS '學號',
  s1.CourseNo AS '課程號',
  s1.score AS '成績'
FROM
  score s1,
  score s2
WHERE
  s1.score = s2.score 
  AND
  s1.CourseNo <> s2.CourseNo
  ORDER BY s1.score DESC, s1.StudentNo, s1.CourseNo

(39)查詢每門課程成績最好的前兩名

SELECT
  s.CourseNo AS '課程號',
  s.StudentNo AS '學號',
  s.score AS '分數'
FROM
  score s
WHERE
  (SELECT COUNT(*) FROM score s1 WHERE s1.CourseNo = s.CourseNo AND s1.score > s.score) < 2
ORDER BY s.CourseNo














持續更新:
2017-06-28

附件列表

     


    免責聲明!

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



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