今日學習內容總結4.6
今日學習內容總結
查詢關鍵字
查詢關鍵字之having過濾
HAVING 關鍵字和 WHERE 關鍵字都可以用來過濾資料,且 HAVING 支援 WHERE 關鍵字中所有的操作符和語法。
但是 WHERE 和 HAVING 關鍵字也存在以下幾點差異:
1. 一般情況下,WHERE 用於過濾資料行,而 HAVING 用於過濾分組。 2. WHERE 查詢條件中不可以使用聚合函式,而 HAVING 查詢條件中可以使用聚合函式。 3. WHERE 在資料分組前進行過濾,而 HAVING 在資料分組後進行過濾 。 4. WHERE 針對資料庫檔案進行過濾,而 HAVING 針對查詢結果進行過濾。也就是說,WHERE 根據資料表中的欄位直接進行過濾,而 HAVING 是根據前面已經查詢出的欄位進行過濾。 5. WHERE 查詢條件中不可以使用欄位別名,而 HAVING 查詢條件中可以使用欄位別名。
而為了更好的區分where與having,將where說成篩選,having說成過濾。
通過這樣的案例來體驗having:
# 統計每個部門年齡在30歲以上的員工的平均薪資並且保留平均薪資大於10000的部門 1. 先獲取每個部門年齡在30歲以上的員工的平均薪資 mysql> select post, avg(salary) from emp where age > 30 group by post; +---------+---------------+ | post | avg(salary) | +---------+---------------+ | teacher | 255450.077500 | | sale | 2500.240000 | +---------+---------------+ 2 rows in set (0.01 sec) 2. 再過濾出平均薪資大於10000的資料 mysql> select post, avg(salary) from emp where age > 30 group by post having avg(salary) > 10000; +---------+---------------+ | post | avg(salary) | +---------+---------------+ | teacher | 255450.077500 | +---------+---------------+ 1 row in set (0.00 sec) # 同時針對聚合函式,我們後續有可能還需要在其他地方作為條件使用,可以先起別名 mysql> select post, avg(salary) as avg_salary from emp where age > 30 group by post having avg_salary > 10000; +---------+---------------+ | post | avg_salary | +---------+---------------+ | teacher | 255450.077500 | +---------+---------------+ 1 row in set (0.01 sec)
查詢關鍵字之distinct去重
去重的前提:資料必須是一模一樣的才可以(如果資料有主鍵肯定無法去重)
比如我們查詢emp表中所有age資料:
mysql> select age from emp; +-----+ | age | +-----+ | 18 | | 78 | | 81 | | 73 | | 28 | | 18 | | 18 | | 48 | | 48 | | 38 | | 18 | | 18 | | 28 | | 28 | | 18 | | 18 | | 18 | | 18 | +-----+ 18 rows in set (0.00 sec)
去重之後:
mysql> select distinct age from emp;
+-----+
| age |
+-----+
| 18 |
| 78 |
| 81 |
| 73 |
| 28 |
| 48 |
| 38 |
+-----+
7 rows in set (0.01 sec)
查詢關鍵字之order by排序
通過實操體驗排序:
1. 通過薪資進行排序
# 預設是升序
mysql> select * from emp order by salary;
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
| 11 | 西西 | female | 18 | 2011-03-12 | sale | NULL | 1000.37 | 402 | 2 |
| 10 | 呵呵 | female | 38 | 2010-11-01 | sale | NULL | 2000.35 | 402 | 2 |
| 5 | owen | male | 28 | 2012-11-01 | teacher | NULL | 2100.00 | 401 | 1 |
| 9 | 哈哈 | female | 48 | 2015-03-11 | sale | NULL | 3000.13 | 402 | 2 |
| 12 | 樂樂 | female | 18 | 2016-05-13 | sale | NULL | 3000.29 | 402 | 2 |
| 4 | tony | male | 73 | 2014-07-01 | teacher | NULL | 3500.00 | 401 | 1 |
| 13 | 拉拉 | female | 28 | 2017-01-27 | sale | NULL | 4000.33 | 402 | 2 |
| 1 | jason | male | 18 | 2017-03-01 | 張江第一帥形象代言 | NULL | 7300.33 | 401 | 1 |
| 3 | kevin | male | 81 | 2013-03-05 | teacher | NULL | 8300.00 | 401 | 1 |
| 6 | jack | female | 18 | 2011-02-11 | teacher | NULL | 9000.00 | 401 | 1 |
| 8 | sank | male | 48 | 2010-11-11 | teacher | NULL | 10000.00 | 401 | 1 |
| 14 | 僧龍 | male | 28 | 2016-03-11 | operation | NULL | 10000.13 | 403 | 3 |
| 18 | 程咬鐵 | female | 18 | 2014-05-12 | operation | NULL | 17000.00 | 403 | 3 |
| 17 | 程咬銅 | male | 18 | 2015-04-11 | operation | NULL | 18000.00 | 403 | 3 |
| 16 | 程咬銀 | female | 18 | 2013-03-11 | operation | NULL | 19000.00 | 403 | 3 |
| 15 | 程咬金 | male | 18 | 1997-03-12 | operation | NULL | 20000.00 | 403 | 3 |
| 7 | jenny | male | 18 | 1900-03-01 | teacher | NULL | 30000.00 | 401 | 1 |
| 2 | tom | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
18 rows in set (0.01 sec)
# 加asc也是升序的意思
select * from emp order by salary asc;
# 加desc是降序
select * from emp order by salary desc;
2. 先按照年齡升序排序,如果年齡相同,則按照薪資降序排序
mysql> select * from emp order by age asc, salary desc;
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
| 7 | jenny | male | 18 | 1900-03-01 | teacher | NULL | 30000.00 | 401 | 1 |
| 15 | 程咬金 | male | 18 | 1997-03-12 | operation | NULL | 20000.00 | 403 | 3 |
| 16 | 程咬銀 | female | 18 | 2013-03-11 | operation | NULL | 19000.00 | 403 | 3 |
| 17 | 程咬銅 | male | 18 | 2015-04-11 | operation | NULL | 18000.00 | 403 | 3 |
| 18 | 程咬鐵 | female | 18 | 2014-05-12 | operation | NULL | 17000.00 | 403 | 3 |
| 6 | jack | female | 18 | 2011-02-11 | teacher | NULL | 9000.00 | 401 | 1 |
| 1 | jason | male | 18 | 2017-03-01 | 張江第一帥形象代言 | NULL | 7300.33 | 401 | 1 |
| 12 | 樂樂 | female | 18 | 2016-05-13 | sale | NULL | 3000.29 | 402 | 2 |
| 11 | 西西 | female | 18 | 2011-03-12 | sale | NULL | 1000.37 | 402 | 2 |
| 14 | 僧龍 | male | 28 | 2016-03-11 | operation | NULL | 10000.13 | 403 | 3 |
| 13 | 拉拉 | female | 28 | 2017-01-27 | sale | NULL | 4000.33 | 402 | 2 |
| 5 | owen | male | 28 | 2012-11-01 | teacher | NULL | 2100.00 | 401 | 1 |
| 10 | 呵呵 | female | 38 | 2010-11-01 | sale | NULL | 2000.35 | 402 | 2 |
| 8 | sank | male | 48 | 2010-11-11 | teacher | NULL | 10000.00 | 401 | 1 |
| 9 | 哈哈 | female | 48 | 2015-03-11 | sale | NULL | 3000.13 | 402 | 2 |
| 4 | tony | male | 73 | 2014-07-01 | teacher | NULL | 3500.00 | 401 | 1 |
| 2 | tom | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
| 3 | kevin | male | 81 | 2013-03-05 | teacher | NULL | 8300.00 | 401 | 1 |
+----+--------+--------+-----+------------+--------------------+--------------+------------+--------+-----------+
18 rows in set (0.00 sec)
3.統計各部門年齡在10歲以上的員工平均薪資,並且保留平均薪資大於1000的部門按照從大到小的順序排序。
mysql> select post, avg(salary) as avg_salary from emp
-> where age > 10
-> group by post
-> having avg_salary > 1000
-> order by avg_salary desc;
+--------------------+---------------+
| post | avg_salary |
+--------------------+---------------+
| teacher | 151842.901429 |
| operation | 16800.026000 |
| 張江第一帥形象代言 | 7300.330000 |
| sale | 2600.294000 |
+--------------------+---------------+
4 rows in set (0.00 sec)
使用ORDER BY 關鍵字應注意以下幾個方面:
1. ORDER BY 關鍵字後可以跟子查詢
2. 當排序的欄位中存在空值時,ORDER BY 會將該空值作為最小值來對待。
3. ORDER BY 指定多個欄位進行排序時,MySQL 會按照欄位的順序從左到右依次進行排序。
查詢關鍵字之limit分頁
在mysql中limit關鍵字用來強制SELECT 語句返回指定的記錄數。
分頁即限制展示條數,通過實操來體驗:
1. 限制展示五條資料:
mysql> select id,name,sex,salary from emp limit 5;
+----+-------+------+------------+
| id | name | sex | salary |
+----+-------+------+------------+
| 1 | jason | male | 7300.33 |
| 2 | tom | male | 1000000.31 |
| 3 | kevin | male | 8300.00 |
| 4 | tony | male | 3500.00 |
| 5 | owen | male | 2100.00 |
+----+-------+------+------------+
5 rows in set (0.00 sec)
2. 分頁效果
mysql> select id,name,sex,salary from emp limit 5, 5;
+----+-------+--------+----------+
| id | name | sex | salary |
+----+-------+--------+----------+
| 6 | jack | female | 9000.00 |
| 7 | jenny | male | 30000.00 |
| 8 | sank | male | 10000.00 |
| 9 | 哈哈 | female | 3000.13 |
| 10 | 呵呵 | female | 2000.35 |
+----+-------+--------+----------+
5 rows in set (0.00 sec)
3. 查詢工資最高的人的詳細資訊
mysql> select * from emp order by salary desc limit 1;
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
| 2 | tom | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
+----+------+------+-----+------------+---------+--------------+------------+--------+-----------+
1 row in set (0.00 sec)
當資料特別多的時候,經常使用limit來限制展示條數,節省資源,防止系統崩潰。
查詢關鍵字之regexp正則
MySQL中正則表示式通常被用來檢索或替換符合某個模式的文字內容,根據指定的匹配模式匹配文中符合要求的特殊字串。
實際操作體驗
# 查詢名字以 j 為開頭,以 n 或 y 結尾的員工的詳細資訊
mysql> select * from emp where name regexp '^j.*(n|y)$';
+----+-------+------+-----+------------+--------------------+--------------+----------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+-------+------+-----+------------+--------------------+--------------+----------+--------+-----------+
| 1 | jason | male | 18 | 2017-03-01 | 張江第一帥形象代言 | NULL | 7300.33 | 401 | 1 |
| 7 | jenny | male | 18 | 1900-03-01 | teacher | NULL | 30000.00 | 401 | 1 |
+----+-------+------+-----+------------+--------------------+--------------+----------+--------+-----------+
2 rows in set (0.00 sec)
我們目前所講的是MySQL查詢關鍵字中使用頻率較高的一些,其實還有一些關鍵字目前無需講解。並且SQL語句裡面同樣還支援流程控制語法。
多表查詢
多表查詢思路
多表查詢思路有兩種:
1. 子查詢
相當於是我們生活中解決問題的方式(一步步解決)
將一條SQL語句的查詢結果加括號當做另一條SQL語句的查詢條件
# 比如以昨天的員工表與部門表為例 查詢jason所在部門名稱
子查詢步驟
1. 先查詢jason所在的部門編號
2. 根據部門編號去部門表中查詢部門名稱
2. 連表操作
先將多張表拼接到一起 形成一張大表 然後基於單表查詢獲取資料
連表操作
1. 先將員工表和部門表按照某個欄位拼接到一起
2. 基於單表查詢
演練資料
create table dep(
id int primary key auto_increment,
name varchar(32)
);
create table emp(
id int primary key auto_increment,
name varchar(32),
gender enum('male','female','others') default 'male',
age int,
dep_id int
);
insert into dep values(200,'技術'),(201,'人力資源'),(202,'銷售'),(203,'運營'),(205,'安保');
insert into emp(name,age,dep_id) values('jason',18,200),('tony',28,201),('oscar',38,201),('jerry',29,202),('kevin',39,203),('jack',48,204);
實際演練
1. 使用子查詢 獲取jason所在的部門名稱
1.1. 先獲取jason的部門編號
select dep_id from emp where name='jason';
1.2. 將結果加括號作為查詢條件
select name from dep where id=(select dep_id from emp where name='jason');
2. 使用連表操作 獲取jason所在的部門名稱
2.1. 笛卡爾積(瞭解知識)
select * from emp,dep; # 會講所有的資料全部對應一遍
select * from emp,dep where emp.dep_id=dep.id; # 效率低下
2.2. 連表操作有四個關鍵字
inner join 內連線
select * from emp inner join dep on emp.dep_id=dep.id;
# 只連線兩張表中有對應關係的資料
left join 左連線
select * from emp left join dep on emp.dep_id=dep.id;
# 以左表為基準 展示所有的資料 沒有對應項則用NULL填充
right join 右連線
select * from emp right join dep on emp.dep_id=dep.id;
# 以右表為基準 展示所有的資料 沒有對應項則用NULL填充
union 全連線
select * from emp left join dep on emp.dep_id=dep.id
union
select * from emp right join dep on emp.dep_id=dep.id;
# 左右兩表資料全部展示 沒有對應項則用NULL填充
如果要想進行笛卡爾積的消除,往往會使用關聯欄位。由於多張表之間可能會有重名的欄位,所以在進行重名欄位訪問的時候,前面需要加上表名稱。採用“表名稱.欄位”的方式來進行訪問。而一條SQL語句的查詢結果,我們也可以看成是一張虛擬表。
視覺化軟體Navicat
什麼是視覺化
資料視覺化軟體可將文字和數字資料轉換為視覺化的圖表,圖形和表格。 通過將重要資料引入中央介面,它被用作建立應用程式/系統性能或操作儀表板的方法。
什麼是Navicat
Navicat是一個可多重連線的資料庫管理工具,它可以連線到MySQL、Oracle、PostgreSQL、SQLite、SQL Server和/或MariaDB資料庫,讓資料庫管理更加方便。Navicat的功能可以滿足專業開發人員的所有需求,對資料庫伺服器的新手來說學習起來也不難。有了極完備的圖形使用者介面(GUI),Navicat可以簡便、安全地建立、組織、訪問和共享資訊。
Navicat提供三種操作平臺:Microsoft Windows、Mac OS X 和Linux。它可以讓使用者連線到本機或遠端伺服器、提供一些實用的資料庫工具如資料模型、資料傳輸、資料同步、結構同步、匯入、匯出、備份、還原、報表建立工具及計劃以協助管理資料。
navicat的下載
Navicat 該軟體是收費的,但是有很多破解版本,自我百度下載即可(正式版只能使用14天)。針對這種圖形化軟體,版本越新越好(不同版本圖示顏色不一樣,但是主題功能是一樣的)。
navicat的使用
注意:navicat的使用是為了提高開發的效率,但是不能太過於依賴該軟體,其實這些軟體的底層還是執行的SQL語句來操作資料庫的,只不過是將SQL語句封裝到軟體內。
使用Navicat第一步首先連線本地MySQL,連線MySQL,輸入密碼,在點選測試即可,不需要輸入HOST,測試成功,會預設填寫。然後查詢MySQL內,庫和表。然後就可以使用了,你可以檢視你原來的庫,也可以直接利用視覺化建立庫等操作。
視覺化軟體內,也可以選擇SQL語句編輯,一些程式碼,視覺化軟體完成不了時,可以自己使用,視覺化軟體提供的SQL語句編輯。
多表查詢練習
-- 1、查詢所有的課程的名稱以及對應的任課老師姓名
# 1.先明確需要幾張表 course表 teacher表
# 2.大致查詢一些表中的資料情況
# 3.既然是多表查詢 那麼查詢思路 子查詢 連表操作(複雜的SQL需要兩者配合使用)
# 4.編寫完成後 使用美化功能 將SQL語句規範化
-- SELECT
-- course.cname,
-- teacher.tname
-- FROM
-- course
-- INNER JOIN teacher ON course.teacher_id = teacher.tid;
-- 4、查詢平均成績大於八十分的同學的姓名和平均成績
# 1.先明確需要用到幾張表 student score
# 2.大致檢視一下兩張表裡面的資料
# 3.先獲取平均成績大於80分的學生資訊(按照student_id分組)
-- select score.student_id,avg(num) as avg_num from score group by score.student_id having avg_num>80;
# 4.結果需要從兩個表裡面的獲取 student SQL語句執行之後的虛擬表
-- SELECT
-- student.sname,
-- t1.avg_num
-- FROM
-- student
-- INNER JOIN ( SELECT student_id, avg( num ) AS avg_num FROM score GROUP BY score.student_id HAVING avg_num > 80 ) AS t1 ON student.sid = t1.student_id;
-- 7、查詢沒有報李平老師課的學生姓名
# 此題有兩種思路 第一種是正向查詢 第二種是反向查詢(先查所有報了李平老師課程的學生id 之後取反即可)
# 1.先明確需要用到幾張表 四張表
# 2.先查詢李平老師的編號
-- select tid from teacher where tname='李平老師'
# 3.再查李平老師教授的課程編號
-- select cid from course where teacher_id=(select tid from teacher where tname='李平老師')
# 4.根據課程編號 去score表中篩選出所有選了課程的學生編號
-- select distinct student_id from score where course_id in (select cid from course where teacher_id=(select tid from teacher where tname='李平老師'));
# 5.根據學生編號去學生表中反向篩選出沒有報李平老師課程的學生姓名
-- SELECT
-- sname
-- FROM
-- student
-- WHERE
-- sid NOT IN ( SELECT DISTINCT student_id FROM score WHERE course_id IN ( SELECT cid FROM course WHERE teacher_id = ( SELECT tid FROM teacher WHERE tname = '李平老師' ) ) )
-- 8、查詢沒有同時選修物理課程和體育課程的學生姓名(兩門都選了和一門都沒選的 都不要 只要選了一門)
# 1.先明確需要用到幾張表 三張
# 2.先獲取物理課程和體育課程的編號
-- select cid from course where cname in ('物理','體育');
# 3.再去分數表中篩選出選了物理和體育的資料(包含了選了一門和兩門 沒有選的就已經被排除了)
-- select * from score where course_id in (select cid from course where cname in ('物理','體育'))
# 4.如何剔除選了兩門的資料(按照學生id分組 然後對課程計數即可)
-- select student_id from score where course_id in (select cid from course where cname in ('物理','體育'))
-- group by student_id HAVING count(course_id) = 1;
# 5.根據上述學生id號篩選出學生姓名
-- SELECT
-- sname
-- FROM
-- student
-- WHERE
-- sid IN (
-- SELECT
-- student_id
-- FROM
-- score
-- WHERE
-- course_id IN ( SELECT cid FROM course WHERE cname IN ( '物理', '體育' ) )
-- GROUP BY
-- student_id
-- HAVING
-- count( course_id ) = 1
-- )
-- 9、查詢掛科超過兩門(包括兩門)的學生姓名和班級
# 1.先明確需要幾張表 三張表
# 2.先去score表中篩選出所有不及格的資料
-- select * from score where num < 60;
# 3.如何篩選每個學生掛科的門數(按照學生id分組 對學科計數即可)
-- select student_id from score where num < 60 group by student_id
-- HAVING count(course_id) >= 2;
# 4.由於最終的結果需要取自兩張表 所以應該拼接
-- select student.sname,class.caption from class inner join student on class.cid=student.class_id;
# 5.使用步驟3獲取到的學生編號 對步驟4的表結果篩選資料
SELECT
student.sname,
class.caption
FROM
class
INNER JOIN student ON class.cid = student.class_id
WHERE
student.sid IN ( SELECT student_id FROM score WHERE num < 60 GROUP BY student_id HAVING count( course_id ) >= 2 );