高級查詢 關鍵字書寫順序 關鍵字執行順序select:投影結果 1 5 from:定位到表 2 1 where:分組前第一道過濾 3 2 group by:分組 4 3 having:分組後第二道過濾 5 4 order by:排序 6 6 limit: 最後 分頁 *目的:為了加快網站對數據的查詢 ...
高級查詢
關鍵字書寫順序 關鍵字執行順序
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