mysql高級查詢


Exists子查詢

Exists的特點

         1.在執行createdrop語句前,可以使用exists語句來判斷數據庫對象是否存在,返回值是truefalse

             比如  

 drop   table    if  exists  student;  意思是如果存在表student則刪除!否則不刪除!

 Create  table   if  not  exists  student;   意思是如果不存在表student則創建,否則不創建!

         2.exists還可以作為where條件的子查詢

                Select  ..... from  表名  where  exists (子查詢);

                意思是:

                     如果子查詢有結果,則返回值為true,繼續執行外層的查詢語句;

                     如果子查詢沒有結果,則返回值是false,外層的查詢語句不會執行。

                  

              

 

-- 檢查“高等數學-1” 課程最近一次考試成績

-- 如果有 80分以上的成績,顯示分數排在前5名的學員學號和分數

 

--  不使用exists

 

 

-- 01.查詢“高等數學-1” 課程 對應的編號

SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1'

 

-- 02.查詢最近的考試成績

SELECT MAX(ExamDate) FROM result

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1')

 

-- 03. 02的基礎上 加條件 成績大於80

SELECT * FROM result

WHERE ExamDate=

(SELECT MAX(ExamDate) FROM result

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1'))

AND StudentResult>80

 

-- 04.優化

SELECT studentNo,StudentResult FROM result

WHERE ExamDate=

(SELECT MAX(ExamDate) FROM result

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1'))

AND StudentResult>80

ORDER BY StudentResult DESC

LIMIT 0,5

 

 

 

--  使用exists

-- 檢查“高等數學-1” 課程最近一次考試成績

-- 如果有 80分以上的成績,顯示分數排在前5名的學員學號和分數

 

-- 01.查詢“高等數學-1” 課程 對應的編號

SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1'

 

-- 02.查詢最近的考試成績

SELECT MAX(ExamDate) FROM result

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1')

 

 

-- 03.查詢學號和成績

SELECT StudentNo,StudentResult FROM result

WHERE  EXISTS

(

SELECT * FROM result

WHERE subjectNo=(

SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1'

)

AND ExamDate=(

SELECT MAX(ExamDate) FROM result

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1')

)

AND StudentResult>80

)

AND subjectNo=(

SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1'

)

AND ExamDate=(

SELECT MAX(ExamDate) FROM result

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

WHERE SubjectName='高等數學-1')

)

ORDER BY StudentResult DESC

LIMIT 0,5

 

Not Exists子查詢

 

-- 檢查“高等數學-1”課程最近一次考試成績

 

-- 如果全部未通過考試(60分及格),認為本次考試偏難,計算的該次考試平均分加5

 

 

 

 

 

-- 01.查詢“高等數學-1” 課程 對應的編號

 

SELECT subjectNo FROM `subject`

 

WHERE SubjectName='高等數學-1'

 

 

 

-- 02.查詢最近的考試成績

 

SELECT MAX(ExamDate) FROM result

 

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

 

WHERE SubjectName='高等數學-1')

 

 

 

 

 

 

 

-- 03.查詢成績大於60的  反着來

 

SELECT StudentResult FROM result

 

WHERE StudentResult>60

 

AND SubjectNo=(

 

SELECT subjectNo FROM `subject`

 

WHERE SubjectName='高等數學-1'

 

)

 

AND ExamDate=(

 

SELECT MAX(ExamDate) FROM result

 

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

 

WHERE SubjectName='高等數學-1')

 

)

 

 

 

 

 

 

 

 

 

-- 04. 如果全部未通過考試,考試平均分加5

 

SELECT AVG(StudentResult)+5  FROM result

 

WHERE NOT EXISTS

 

(

 

SELECT StudentResult FROM result

 

WHERE StudentResult>60

 

AND SubjectNo=(

 

SELECT subjectNo FROM `subject`

 

WHERE SubjectName='高等數學-1'

 

)

 

AND ExamDate=(

 

SELECT MAX(ExamDate) FROM result

 

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

 

WHERE SubjectName='高等數學-1')

 

)

 

)

 

AND SubjectNo=(

 

SELECT subjectNo FROM `subject`

 

WHERE SubjectName='高等數學-1'

 

)

 

AND ExamDate=(

 

SELECT MAX(ExamDate) FROM result

 

WHERE SubjectNo=(SELECT subjectNo FROM `subject`

 

WHERE SubjectName='高等數學-1')

 

)

 

 

 

 

 

 

 

-- 如果有 年級名稱是大二 的學生,就 查詢出 年級名稱是大一的 所有學生信息

 

 

 

--  01.先查詢出 對應的年級編號

 

SELECT GradeId FROM grade  WHERE GradeName='大一'

 

SELECT GradeId FROM grade  WHERE GradeName='大二'

 

 

 

--  02.在學生表中是否存在  年級名稱是大二 的學生

 

SELECT * FROM  student  WHERE  gradeID=(

 

SELECT GradeId FROM grade  WHERE GradeName='大二'

 

)

 

 

 

-- 03.如果有查詢出 年級名稱是大一的 所有學生信息

 

SELECT * FROM student

 

WHERE  EXISTS

 

(

 

SELECT * FROM  student  WHERE  gradeID=(

 

SELECT GradeId FROM grade  WHERE GradeName='大二'

 

)

 

)

 

AND GradeId=(

 

SELECT GradeId FROM grade  WHERE GradeName='大一'

 

)

 

 

ExistsIN , Not ExistsNot IN 的區別

 

 

 01. INNot IN 做的是一個區間的判斷,查詢數據是否在區間內

        ExistsNot Exists都是根據查詢語句返回true或者false!

     

     02.  例子:

select  a.* from  A  a

 where  a.id  in(select id from B)

  如果A表中有1000條數據

       B表中有1000條數據

  分析步驟:

      01. select id from B 會查詢出B表中的所有id,然后緩存起來,共1000條(因為使用in 會先執行子查詢

      02.然后分別拿A表中的每一個idB表中的1000id進行比較,也就是比較了 1000*1000

      03.這樣效率是非常慢的

      04.如果B表中只有100或者10條數據(只是舉例說明數據量小),那么就會比較1000*10

         這樣相對來說效率會高點!

 

 結論:

子查詢中涉及的表(B)數據量小於 主查詢中涉及的表(A)數據量 時,使用In來查詢!可以提高效率

In 查詢做的是 外表和內表的hash連接

hash連接就是  以 外層查詢的表作為hash table ,內層查詢的表在hash table中查詢數據!

 很顯然,如果內層查詢的數量大 ,查詢效率就慢,查詢數據量小,效率就高!

 

 

03. 例子:

  select  a.* from  A  a

 where  exists  (select id from B b where a.id=b.id)

  如果A表中有1000條數據

       B表中有1000條數據

  分析步驟:

      01. 使用了exists會以外層查詢為驅動)上面的sql語句只會執行1000次(因為A表中有多少條數據,就會執行幾次)

      02. exists查詢不需要數據的結果集,只需要返回true或者false

結論:

子查詢中涉及的表(B)數據量大於 主查詢中涉及的表(A)數據量時,使用exists來查詢!可以提高效率

Exists查詢做的是loop循環

 

 04. 如果子查詢中涉及的表(B)數據量 和 主查詢中涉及的表(A)數據量 差不多時,建議使用IN來查詢!

     因為In查詢是在內存中的查詢,exists需要查詢數據庫,所以內存中的查詢肯定比查詢數據庫性能高!

 

 05.not exists 在任何時候都比not in 效率高!

          因為not in 那么內外表都進行全表掃描,沒有用到索引not  exists的子查詢仍然可以用到索引!

 

any,some,all的使用

 

SELECT * FROM student

 

WHERE studentname

 

IN(SELECT studentName FROM student)

 

 

 

--  使用any(只要是在區間就行) 替換in   

 

SELECT * FROM student

 

WHERE studentname=ANY(SELECT studentName FROM student)

 

 

 

 

 

-- all  滿足子查詢中編號最大的

 

SELECT * FROM student WHERE

 

studentNo>ALL

 

(SELECT studentNo FROM student WHERE studentNo IN(1014,1001,1002))

 

 

 

-- any   滿足子查詢中編號最小的

 

SELECT * FROM student WHERE

 

studentNo>ANY

 

(SELECT studentNo FROM student WHERE studentNo IN(1014,1001,1002))

 

 

 

--  和  any 效果一致

 

SELECT * FROM student WHERE

 

studentNo>SOME

分組查詢

-- 分組  group by

--  01. 查詢 每門課程的名稱 以及平均分

--  並且按照平均分降序排列

SELECT  subjectName,AVG(StudentResult)

FROM  `result` r,`subject` s

WHERE

r.`SubjectNo`=s.`SubjectNo`

GROUP BY subjectName

ORDER BY AVG(StudentResult) DESC

 

 

-- 02.在上述案例中增加   條件  having

--  平均分>73的 顯示

SELECT  subjectName,AVG(StudentResult)

FROM  `result` r,`subject` s

WHERE

r.`SubjectNo`=s.`SubjectNo`

GROUP BY subjectName

HAVING AVG(StudentResult)>73

ORDER BY AVG(StudentResult) DESC

 

 

-- 03.統計每個年級的男女人數   多列進行分組

SELECT   gradeid '年級編號',COUNT(sex) '性別人數',sex '性別'

FROM student

WHERE sex IS NOT NULL AND gradeid IS NOT NULL

GROUP BY gradeid,sex

 

 

-- 04. 找出每個課程成績的前三名

SELECT * FROM result r1

WHERE

(

SELECT  COUNT(1) FROM  result r2

WHERE r1.subjectNo=r2.`SubjectNo`

AND r1.studentresult<r2.studentresult

)<3

ORDER BY subjectNo,studentResult DESC

多表連接查詢

比如之前寫的小例子,查詢學生的成績,我們獲取的是學生編號和成績!

但是如果獲取了學生姓名和成績豈不是更好? 但是學生姓名和成績不在一張表中!

這時候就需要我們的連接查詢!

      常用的連接查詢方式:

01. 內連接

02. 外連接

 

內連接

內連接是典型的最常用的連接查詢! 特點就是兩個表中存在主外健關系時,通常使用!

        查詢兩張表中共同的數據!

      

       內連接的實現方式有兩種:

     

      01. where條件中指定連接條件

            比如 查詢學生姓名以及對應的年級名稱

 

            Select  studentName,gradeName

 from student,grade

Where student.gradeId=grade.gradeId

      

      02.form 子句中增加 inner join  on 關系

 

        比如查詢學生姓名,科目名稱以及考試成績

SELECT  studentName,subjectName,studentresult

FROM student s

INNER JOIN result r ON s.studentNo=r.studentNo

INNER JOIN  `subject` su ON  su.subjectNo=r.subjectNo

 

 注意點:

  001.inner可以省略

  002.inner join 用來連接兩個表

  003.on用來設置條件

  004. s  r  su是用的別名

 

外連接

 

 

外連接查詢是至少返回一個表中的所有記錄,根據匹配條件有選擇地返回另一張表的數據!

 

         外連接有主表和從表的概念!

 

         以主表為准匹配從表的數據,符合連接條件的數據直接返回到結果集中,不符合的數據將被賦予null之后再返回到結果集中!

 

 

 

               外連接查詢又分為:

 

01.左外連接    Left  outer  join

 

以左表為主表,從表(右邊的表)中如果沒有匹配的數據返回null

 

例子1: 查詢學生的姓名,考試科目以及成績!

 

 

 

SELECT  studentName,subjectNo,studentResult FROM  student s

 

LEFT JOIN  result r  ON r.`studentNo`=s.`studentNo`

 

 

 

例子2:查詢所有科目對應的學生成績

 

SELECT  subjectName,s.subjectNo,studentResult FROM

 

`subject`  s LEFT JOIN result r

 

ON s.`SubjectNo`=r.`SubjectNo`

 

 

 

 

 

02.右外連接 right outer  join

 

以右表為主表,從表(左邊的表)中如果沒有匹配的數據返回null

 

 

 

  例子:查詢年級名稱和學生名稱       兩個結果是否一致?

 

                         SELECT gradeName,studentName FROM grade

 

RIGHT JOIN student ON grade.`GradeID`=student.`GradeId`

 

 

 

SELECT gradeName,studentName FROM grade

 

INNER JOIN student ON grade.`GradeID`=student.`GradeId`

 


免責聲明!

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



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