1. 程式人生 > >高級查詢語句____ Mysql

高級查詢語句____ Mysql

計算 數據庫 運算 現在 del 字段名 server 機制 between

MySQL高級查詢


高級查詢


關鍵字書寫順序 關鍵字執行順序
select:投影結果 1 5

from:定位到表 2 1

where:分組前第一道過濾 3 2

group by:分組 4 3

having:分組後第二道過濾 5 4

order by:排序 6 6

limit: 最後


---分頁 *
目的:為了加快網站對數據的查詢(檢索)速度

--sql server :
-1.跳過前幾條,取剩下的幾條數據
雙top 雙order by
select top 每頁數據量 * from 表 where 列 not in
(
select top 要跳過的數據量 列 from 表
)
-----------------------------
---------------------------------------------------------
-2.row_nubmer() over( ORDER BY ) (2005以後支持)
select * from
(
select *,row_number() over(order by 主鍵列) as myid from 表
) as temp
where myid between 起始號碼 and 每頁數據量


--mysql :

SELECT <字段名列表>
FROM <表名或視圖>
[WHERE <查詢條件>]
[GROUP BY <分組的字段名>]
[ORDER BY <排序的列名> [ASC 或DESC]]
[LIMIT [位置偏移量,]行數];

--臨時表
臨時表主要用於對大數據量的表上作一個子集,提高查詢效率。加快數據訪問速度
臨時表存在於系統數據庫
SQL Sever :
存在於系統數據庫tempdb
#表名:局部臨時表:
只對當前會話有效
##表名:全局臨時表
所有會話共享

MySQL :
在會話斷開銷毀
所有臨時表都是服務於當前連接
臨時表只在當前連接可見,當關閉連接時,Mysql會自動刪除表並釋放所有空間。因此在不同的連接中可以創建同名的臨時表,並且操作屬於本連接的臨時表。
創建臨時表的語法與創建表語法類似,不同之處是增加關鍵字TEMPORARY,如:
CREATE TEMPORARY TABLE 表名 (…. )
show create table可以查看臨時表;

--偽表
dual 我們稱之為 偽表!

在mysql中是一個擺設

select *;
select * from dual;

select * from dual; 報錯


oracle中 必須使用 from dual;
select * from dual; 正確的
select * ; 錯誤


dual是一個只有一行一列的表!
只能查詢! 不能對 dual進行增刪改!

技術分享圖片
--和並列
DROP TABLE IF EXISTS `testa`;
CREATE TABLE `testa` (
  `name` varchar(20) DEFAULT NULL,
  `subject` varchar(20) DEFAULT NULL,
  `score` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
insert  into `testa`(`name`,`subject`,`score`) values (‘張三‘,‘語文‘,80),(‘李四‘,‘語文‘,90),(‘王五‘,‘語文‘,70),(‘張三‘,‘數學‘,60),(‘李四‘,‘數學‘,98),(‘王五‘,‘數學‘,100);

--  需要成績和科目 在一列 顯示  根據name分組
SELECT  
`name` AS  姓名,
GROUP_CONCAT(`subject`,‘:‘,score) AS  成績
FROM  testa
GROUP BY  `name`;

 
  

 -- 查詢所有年級編號為1的學員信息,按學號升序排序
SELECT * FROM student
WHERE GradeID=1
ORDER BY Studentno ASC; 
-- 顯示前4條記錄
SELECT * FROM student
WHERE GradeID=1
ORDER BY Studentno ASC
LIMIT 0,4;
-- 每頁4條,顯示第2頁,即從第5條記錄開始顯示4條數據
SELECT * FROM student
WHERE GradeID=1
ORDER BY Studentno ASC
LIMIT 4,4
技術分享圖片


SQL99標準:
(1)是操作所有關系型數據庫的規則
(2)是第四代語言
(3)是一種結構化查詢語言 s
(4)只需發出合法合理的命令,就有對應的結果顯示


<>:不等於(SQL99標準)

-- 子查詢
相關和嵌套
相關子查詢: 執行機制
內層查詢不能單獨執行,需要和外部的查詢進行結合。外層和內層並行執行。|
嵌套子查詢: 內層查詢可以單獨執行。內層的結果作為外層的條件
註意:並不是所有子查詢都是先執行內層查詢

子查詢可以應用到任何位置

所有表連接都可以使用子查詢替換,但是能用子查詢的地方,未必都能夠使用表連接
舉例: 限制:不能使用表連接場景:::查詢條件為<>時

(結論:子查詢應用範圍更廣)
一個查詢中又包含了另一個查詢,一般來說,子查詢會使用()擴起來,並且小括號內的檢索結果會作為外層查詢的條件存在

比較運算符 只能投影一列 in,not in,not exists和exists可投影多列

技術分享圖片
-- 把一個查詢的結果 當成另一個查詢的 字段,條件或者表(子查詢可以應用到任何位置)!
SELECT  studentName FROM  student
--  只能通過student 表 查詢出 學生對應的 年級名稱
--  01. 先查詢出 學生 武松 對應的  年級編號
SELECT    GradeID  FROM student WHERE  studentName=‘武松‘
--  02.根據年級編號  取  年級名稱
SELECT gradeName FROM grade WHERE GradeID=???
SELECT gradeName FROM grade WHERE GradeID
=(SELECT    GradeID  FROM student WHERE  studentName=‘武松‘)

 -- 查詢年級編號是1或者2 的  所有學生列表
 SELECT * FROM student WHERE gradeId IN(1,2)
-- 查詢 年級名稱是  大一或者大二的所有學生信息
 -- 學生表 中沒有  年級名稱  但是有年級編號
 -- 01.根據  年級名稱 查詢出 編號
 
SELECT gradeID FROM grade WHERE gradeName IN(‘大一‘,‘大二‘);
 -- 02.再根據id查詢學生信息
SELECT  * FROM student WHERE 
gradeID 
IN (SELECT gradeID FROM grade WHERE gradeName IN(‘大一‘,‘大二‘)) 
 
 -- 查詢參加 最近一次 高等數學-1 考試成績的學生的最高分和最低分
-- 01. 發現成績表中 沒有 科目名稱 只有編號!根據名稱取編號
SELECT  SubjectNo  FROM `subject`  WHERE
subjectName=‘高等數學-1‘
-- 02.查詢最近一次 高等數學-1 考試的時間
SELECT  MAX(ExamDate)  FROM result
WHERE 
SubjectNo=(SELECT  SubjectNo  FROM `subject`  WHERE
subjectName=‘高等數學-1‘)
--  所有最近考試的成績
SELECT *  FROM result
WHERE ExamDate=‘2013-11-11 16:00:00‘
-- 03.開始獲取最高分和 最低分
SELECT  MAX(studentResult) AS 最高分,
        MIN(studentResult) AS 最低分
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‘))
 
技術分享圖片

技術分享圖片
-- 查詢 高等數學-1 考試成績是 60 分的 學生信息
-- 01.根據  科目名稱 獲取 科目編號
SELECT SubjectNo  FROM  `subject`
WHERE SubjectName=‘高等數學-1‘
-- 02.根據編號 查詢 所有的學生編號
SELECT studentNo FROM result 
WHERE SubjectNo=(SELECT SubjectNo  FROM  `subject`
WHERE SubjectName=‘高等數學-1‘)
AND StudentResult=60;  -- 成績=60
-- 03.查詢學生信息
SELECT * FROM  student
WHERE  studentNo IN
(SELECT studentNo FROM result 
WHERE SubjectNo=(SELECT SubjectNo  FROM  `subject`
WHERE SubjectName=‘高等數學-1‘)
AND StudentResult=60)

-- 使用in替換 等於(=)的子查詢語句!
-- in後面的子查詢可以返回多條記錄!

--  not in :不在某個範圍之內
-- 查詢未參加 “高等數學-1” 課程最近一次考試的在讀學生名單
-- 01.根據  科目名稱 獲取 科目編號
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,StudentName FROM student
WHERE studentNo NOT IN
(
SELECT  StudentNo  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‘))
)
 
 
 
技術分享圖片


- exists(檢查子查詢)的使用
-- 01. 用於檢測表,數據庫等等 是否存在
-- 02. 檢查子查詢中是否會返回數據!檢查子查詢並不返回任何數據!
值返回 true或者false!
1.Exists使用場景?
判定數據庫對象是否存在
1.1
if exists XXXX
1.2
where exists(子查詢)

技術分享圖片
SELECT * FROM Student WHERE EXISTS(SELECT NULL)
SELECT * FROM Student WHERE EXISTS(SELECT 9*9)
SELECT * FROM Student WHERE EXISTS(SELECT StudentName FROM student) 

SELECT * FROM Student 
WHERE EXISTS(SELECT studentName FROM Student WHERE studentName=‘張三‘)
SELECT * FROM Student WHERE studentName IN(SELECT studentName FROM Student)
 -- in  效果等同於 =any
SELECT * FROM Student WHERE 
studentName =ANY(SELECT studentName FROM Student)

--  all 大於子查詢語句中的 最大值   >(1,2,3)    >3
SELECT * FROM student
WHERE studentNo>ALL
(SELECT studentNo FROM student WHERE studentNo IN(1003,1004,1005))
--  any 大於子查詢語句中的 最小值   >(1,2,3)   >1
SELECT * FROM student
WHERE studentNo>ANY
(SELECT studentNo FROM student WHERE studentNo IN(1003,1004,1005))
--  some 和any功能一樣
SELECT * FROM student
WHERE studentNo>SOME
(SELECT studentNo FROM student WHERE studentNo IN(1003,1004,1005))

-- 檢查“高等數學-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=‘大一‘
)
技術分享圖片

-- 使用子查詢的註意事項
-- 01.任何允許使用表達式的地方都可以使用子查詢
-- 02.只出現在子查詢中但是沒有在父查詢中出現的列,結果集中的列不能包含!

sql優化

使用exists 代替 in
使用not exists 代替not in

exists 只返回true或者false.不返回結果集
in 返回結果集

技術分享圖片
-- 查詢姓李的學生信息   % 代表0或者多個字符  _代表一個字符
SELECT * FROM student WHERE StudentName LIKE ‘李%‘
SELECT * FROM student WHERE StudentName LIKE ‘李_‘
-- 使用in完成上述代碼
SELECT * FROM student WHERE StudentName IN(
SELECT studentName FROM student WHERE StudentName LIKE ‘李%‘)
--  in(多條數據--》返回結果集)
-- 使用exists替換
SELECT * FROM student WHERE EXISTS(
SELECT studentName FROM student)
AND StudentName LIKE ‘李%‘
-- exists(有沒有數據)
 

-- 統計每門課程平均分各是多少 GROUP BY  列名 分組
SELECT subjectno,AVG(studentresult)  FROM result
GROUP BY  subjectno
-- 查詢出課程平均分大於60的課程編號 和 平均分
SELECT subjectno,AVG(studentresult)  FROM result
GROUP BY  subjectno
HAVING AVG(studentresult)>60   -- 分組之後的條件
-- 統計每門課程平均分各是多少 降序排列
SELECT subjectno,AVG(studentresult)  FROM result
GROUP BY  subjectno
ORDER BY AVG(studentresult) DESC
-- 如果成績相同  再按照 課程編號 升序排序
SELECT subjectno,AVG(studentresult)  FROM result
GROUP BY  subjectno
ORDER BY AVG(studentresult) DESC,subjectno 
-- 分組統計每個年級的 男女人數
SELECT  gradeid 年級編號,sex 性別,COUNT(sex) 人數
FROM student
GROUP BY gradeid,sex
技術分享圖片

技術分享圖片
-- 創建表
CREATE TABLE IF NOT  EXISTS   examTest(
 id  INT(2) NOT NULL,
 sex VARCHAR(20) 
)
-- 同時新增多條數據
INSERT INTO examTest  VALUES(1,‘男‘),(2,‘男‘),(3,‘女‘),(4,NULL);
SELECT sex AS ‘性別‘,COUNT(sex) AS ‘人數‘ FROM examTest
WHERE sex IS NOT NULL
GROUP BY sex
ORDER BY COUNT(sex) DESC 

SELECT sex AS ‘性別‘,COUNT(sex) AS ‘人數‘ FROM examTest
GROUP BY sex
HAVING sex IS NOT NULL
ORDER BY COUNT(sex) DESC 
SELECT sex AS ‘性別‘,COUNT(sex) AS ‘人數‘ FROM examTest
WHERE  sex IN(‘男‘,‘女‘)
GROUP BY sex
ORDER BY COUNT(sex) DESC 
 

-- 創建表 
CREATE  TABLE IF NOT EXISTS mytable(
`name` VARCHAR(10) NOT NULL,
class  INT(4) NOT NULL,
sorce  DOUBLE NOT NULL
)
-- 插入數據
INSERT INTO mytable 
VALUES
(‘小黑1‘,1,88),(‘小黑2‘,1,80),
(‘小黑3‘,1,68),(‘小黑4‘,1,70),
(‘小黑5‘,1,98),(‘小黑6‘,1,90),
(‘小白1‘,2,88),(‘小白2‘,2,80),
(‘小白3‘,2,68),(‘小白4‘,2,70),
(‘小白5‘,2,98),(‘小白6‘,2,90)
--  找出表中分數的前三名
SELECT * FROM mytable
ORDER BY sorce DESC
LIMIT 0,3
--  找出每個班級的前三名   
SELECT * FROM mytable t1
WHERE
(
SELECT COUNT(1) FROM mytable t2
WHERE   t1.`sorce`<t2.`sorce`
AND t1.class=t2.`class`
)<3
ORDER BY class,sorce DESC
 
技術分享圖片

內鏈接中的 結果集 :
笛卡爾積 :兩個表記錄的乘積!
笛卡爾積又叫笛卡爾乘積,是一個叫笛卡爾的人提出來的。
簡單的說就是兩個集合相乘的結果。
笛卡爾乘積是指在數學中,兩個集合X和Y的笛卡尓積(Cartesian product),又稱直積,表示為X × Y,第一個對象是X的成員而第二個對象是Y的所有可能有序對的其中一個成員[1] 。

表連接中
on 兩個表通過哪一列建立關聯關系
(所有表連接同理)

內連接 :通過匹配兩個表中公共列,找到 公共的行!

左外連接: 以左表為準,右表中沒有數據返回null

右外連接: 以右表為準,左表中沒有數據返回null

隱式內連接: 通過匹配兩個表中公共列,找到 公共的行!

自連接 把一個表當成多個表來使用 關鍵是 使用別名

技術分享圖片
-- 輸出學生姓名以及對應的年級名稱   內連接
SELECT StudentName,GradeName  FROM  student INNER JOIN grade
ON student.`GradeId`=grade.`GradeID`
--  隱式內連接
SELECT StudentName,GradeName  FROM  student,grade
WHERE student.`GradeId`=grade.`GradeID`
-- 查詢 考試 課程編號是1的 學生姓名 以及年級名稱 和科目名稱以及成績
01.
SELECT s.StudentName,GradeName,SubjectName ,studentResult FROM student s
INNER JOIN grade g  ON (s.gradeID=g.gradeID)
INNER JOIN `subject` b ON(g.gradeID=b.gradeID)
INNER JOIN result  r ON (b.subjectNo=r.subjectNo)
AND s.studentNo=r.studentNo
AND b.subjectNo=1
技術分享圖片


02.

技術分享圖片
SELECT StudentName,GradeName,SubjectName ,studentResult FROM
student s,grade g,`subject` b,result  r
WHERE s.gradeID=g.gradeID
AND g.gradeID=b.gradeID
AND s.studentNo=r.studentNo
AND b.subjectNo=r.subjectNo
AND b.subjectNo=1
--  查詢的列 不在同一個表中!  必須使用連接查詢!建立關聯關系!
 --  臨時表只有當前連接可見 隨連接的關閉 自動刪除
  --  臨時表的增刪改 不會影響到 真表
  CREATE TEMPORARY TABLE myStudent
  (SELECT * FROM student)
  
  SELECT * FROM myStudent
  DELETE FROM mystudent  -- 臨時表的數據刪除
  SELECT * FROM student -- 不會影響到真表
技術分享圖片

自連接

技術分享圖片
--  自連接    把一個表當成多個表來使用   關鍵是 使用別名
 SELECT * FROM teacher
 --  查詢 老師3 的姓名和  對應的 導師的姓名
 --  t1  老師   t2  導師    老師的導師編號===  導師的編號
 SELECT t1.`name` AS a,t2.`name` AS 導師姓名  FROM teacher t1,teacher t2
 WHERE  t1.`name`=‘老師3‘
 AND t2.id=t1.tid
技術分享圖片

高級查詢語句____ Mysql