準備資料
以下操作將在該表中進行
create table student (
id int unsigned primary key auto_increment,
name char(12) not null,
gender enum("male","famale") default "male",
age tinyint unsigned not null,
hoc_group char(12) not null,
html tinyint unsigned not null,
css tinyint unsigned not null,
js tinyint unsigned not null,
sanction enum("大處分","小處分","無")
);
insert into student(name,gender,age,hoc_group,html,css,js,sanction) values
("Yunya","male",18,"first",88,93,76,"無"),
("Jack","male",17,"second",92,81,88,"無"),
("Bella","famale",17,"first",72,68,91,"小處分"),
("Dairis","famale",18,"third",89,54,43,"大處分"),
("Kyle","famale",19,"fifth",31,24,60,"大處分"),
("Alice","famale",16,"second",49,23,58,"無"),
("Ken","male",16,"third",33,62,17,"大處分"),
("Jason","male",21,"fourth",91,92,90,"無"),
("Tom","male",20,"fifth",88,72,91,"無"),
("Fiona","famale",19,"fourth",60,71,45,"無");
查詢語法
SELECT DISTINCT(欄位名1,欄位名2...) FROM 表名
WHERE 條件
GROUP BY 欄位名
HAVING 篩選
ORDER BY 欄位名 asc/desc
LIMIT 限制條數;
執行順序
雖然查詢的書寫語法是上面那樣的,但是其內部執行順序卻有些不太一樣。
1.通過
from
找到將要查詢的表2.
where
規定查詢條件,在表記錄中逐行進行查詢並篩選出符合規則的記錄3.將查到的記錄進行欄位分組
group by
,如果沒有進行分組,則預設為一組4.將分組得到的結果進行
having
篩選,可使用聚和函式(where
時不可使用聚合函式)5.執行
select
準備列印6.執行
distinct
對列印結果進行去重7.執行
ordery by
對結果進行排序8.執行
limit
對列印結果的條數進行限制
select
select
主要復負責列印相關的工作
全部查詢
使用select * from 表名
可拿到該表下全部的資料
以下示例將展示使用全部查詢拿到student
表中所有記錄
select * from student;
+----+--------+--------+-----+-----------+------+-----+----+-----------+
| id | name | gender | age | hoc_group | html | css | js | sanction |
+----+--------+--------+-----+-----------+------+-----+----+-----------+
| 1 | Yunya | male | 18 | first | 88 | 93 | 76 | 無 |
| 2 | Jack | male | 17 | second | 92 | 81 | 88 | 無 |
| 3 | Bella | famale | 17 | first | 72 | 68 | 91 | 小處分 |
| 4 | Dairis | famale | 18 | third | 89 | 54 | 43 | 大處分 |
| 5 | Kyle | famale | 19 | fifth | 31 | 24 | 60 | 大處分 |
| 6 | Alice | famale | 16 | second | 49 | 23 | 58 | 無 |
| 7 | Ken | male | 16 | third | 33 | 62 | 17 | 大處分 |
| 8 | Jason | male | 21 | fourth | 91 | 92 | 90 | 無 |
| 9 | Tom | male | 20 | fifth | 88 | 72 | 91 | 無 |
| 10 | Fiona | famale | 19 | fourth | 60 | 71 | 45 | 無 |
+----+--------+--------+-----+-----------+------+-----+----+-----------+
欄位查詢
使用select 欄位名1,欄位名2 from 表名
可拿到特定欄位下相應的資料
以下示例將展示使用欄位查詢拿到每個學生的HTML\CSS\JS
成績
select name,html,css,js from student;
+--------+------+-----+----+
| name | html | css | js |
+--------+------+-----+----+
| Yunya | 88 | 93 | 76 |
| Jack | 92 | 81 | 88 |
| Bella | 72 | 68 | 91 |
| Dairis | 89 | 54 | 43 |
| Kyle | 31 | 24 | 60 |
| Alice | 49 | 23 | 58 |
| Ken | 33 | 62 | 17 |
| Jason | 91 | 92 | 90 |
| Tom | 88 | 72 | 91 |
| Fiona | 60 | 71 | 45 |
+--------+------+-----+----+
as 別名
使用select 欄位名1 as 別名1, 欄位名2 as 別名2 from 表名
可將查詢到的記錄欄位修改一個別名
以下示例將展示修改name
欄位為姓名
,修改gender
欄位為性別
,修改age
欄位為年齡
的操作
select name as "姓名", gender as "性別", age as "年齡" from student;
+--------+--------+--------+
| 姓名 | 性別 | 年齡 |
+--------+--------+--------+
| Yunya | male | 18 |
| Jack | male | 17 |
| Bella | famale | 17 |
| Dairis | famale | 18 |
| Kyle | famale | 19 |
| Alice | famale | 16 |
| Ken | male | 16 |
| Jason | male | 21 |
| Tom | male | 20 |
| Fiona | famale | 19 |
+--------+--------+--------+
distinct
使用select distinct(欄位名1, 欄位名2) from 表名
可將查詢到的記錄做一個取消重複的操作
以下示例將展示使用去重功能來看有多少個小組
select distinct(hoc_group) from student;
+-----------+
| hoc_group |
+-----------+
| first |
| second |
| third |
| fifth |
| fourth |
+-----------+
四則運算
查詢結果可進行四則運算,以下示例將展示拿到每個同學三科總分的操作
select name, html+css+js as 總成績 from student;
+--------+-----------+
| name | 總成績 |
+--------+-----------+
| Yunya | 257 |
| Jack | 261 |
| Bella | 231 |
| Dairis | 186 |
| Kyle | 115 |
| Alice | 130 |
| Ken | 112 |
| Jason | 273 |
| Tom | 251 |
| Fiona | 176 |
+--------+-----------+
顯示格式
使用concat()
可將查詢結果與任意字串進行拼接
使用concat_ws()
可指定連線符進行拼接,第一個引數是連線符
select concat("姓名->",name," ","性別->",gender) from student; # 合併成了一個字串,注意用的空格分隔開的,不然會黏在一起
+--------------------------------------------------+
| concat("姓名->",name," ","性別->",gender) |
+--------------------------------------------------+
| 姓名->Yunya 性別->male |
| 姓名->Jack 性別->male |
| 姓名->Bella 性別->famale |
| 姓名->Dairis 性別->famale |
| 姓名->Kyle 性別->famale |
| 姓名->Alice 性別->famale |
| 姓名->Ken 性別->male |
| 姓名->Jason 性別->male |
| 姓名->Tom 性別->male |
| 姓名->Fiona 性別->famale |
+--------------------------------------------------+
select concat_ws("|||",name,gender,age) from student; # 使用|||為每個欄位進行分割
+----------------------------------+
| concat_ws("|||",name,gender,age) |
+----------------------------------+
| Yunya|||male|||18 |
| Jack|||male|||17 |
| Bella|||famale|||17 |
| Dairis|||famale|||18 |
| Kyle|||famale|||19 |
| Alice|||famale|||16 |
| Ken|||male|||16 |
| Jason|||male|||21 |
| Tom|||male|||20 |
| Fiona|||famale|||19 |
+----------------------------------+
where
where
條件是查詢的第一道坎,能有效過濾出我們想要的任意資料
比較運算
使用比較運算子> < >= <= !=
進行查詢
以下示例將展示使用where
過濾出js
成績大於80分的同學
select name, js from student where js > 80;
+-------+----+
| name | js |
+-------+----+
| Jack | 88 |
| Bella | 91 |
| Jason | 90 |
| Tom | 91 |
+-------+----+
邏輯運算
使用and or not
可進行邏輯運算與多條件查詢
以下示例將展示使用where
多條件查詢過濾出各科成績都大於80分的同學
select name, html, css, js from student where html > 80 and css > 80 and js > 80;
+-------+------+-----+----+
| name | html | css | js |
+-------+------+-----+----+
| Jack | 92 | 81 | 88 |
| Jason | 91 | 92 | 90 |
+-------+------+-----+----+
成員運算
in
可以在特定的值中進行獲取,如in(80,90,100)
則代表只取80或者90或者100的這幾條記錄。
以下示例將展示只取第一組first
以及第二組second
學生的個人資訊
select name, gender, age, hoc_group from student where hoc_group in ("first","second");
+-------+--------+-----+-----------+
| name | gender | age | hoc_group |
+-------+--------+-----+-----------+
| Yunya | male | 18 | first |
| Jack | male | 17 | second |
| Bella | famale | 17 | first |
| Alice | famale | 16 | second |
+-------+--------+-----+-----------+
between and
between and
也是取區間的意思,
以下示例將展示使用between and
過濾出Js
成績大於等於60並且小於80的同學
select name, js from student where js between 60 and 80;
+-------+----+
| name | js |
+-------+----+
| Yunya | 76 |
| Kyle | 60 |
+-------+----+
like
like
是模糊查詢,其中%
代表任意多個字元(類似於貪婪匹配的萬用字元.*
),_
代表任意一個字元(類似於非貪婪匹配的萬用字元.*?
)。
以下示例將展示使用like/%
匹配出姓名以k
開頭的所有同學的名字
select name from student where name like "k%";
+------+
| name |
+------+
| Kyle |
| Ken |
+------+
以下示例將展示使用like/_
匹配出姓名以k
開頭並整體長度為3的同學的名字
select name from student where name like "k__";
+------+
| name |
+------+
| Ken |
+------+
正則匹配
使用RegExp
可進行正則匹配,以下示例將展示使用正則匹配出名字中帶有k
的所有同學姓名
select name from student where name REGEXP "k+";
+------+
| name |
+------+
| Jack |
| Kyle |
| Ken |
+------+
group by
分組行為發生在where
條件之後,我們可以將查詢到的記錄按照某個相同欄位進行歸類,一般分組都會配合聚合函式進行使用。
需要注意的是select
語句是排在group by
條件之後的,因此聚合函式也能在select
語句中使用。
基本使用
以下示例將展示對hoc_group
欄位進行分組。
我們按照
hoc_group
欄位進行分組,那麼select
查詢的欄位只能是hoc_group
欄位,想要獲取組內的其他欄位相關資訊,需要藉助函式來完成
select hoc_group from student group by hoc_group;
+-----------+
| hoc_group |
+-----------+
| fifth |
| first |
| fourth |
| second |
| third |
+-----------+
如果不使用分組,則會產生重複的資訊
mysql> select hoc_group from student;
+-----------+
| hoc_group |
+-----------+
| first |
| second |
| first |
| third |
| fifth |
| second |
| third |
| fourth |
| fifth |
| fourth |
+-----------+
group_concat
用什麼欄位名進行分組,在select
查詢時就只能查那個用於分組的欄位,查詢別的欄位會丟擲異常,會提示sql_mode
異常。
我們將Js
成績大於80
分的同學篩選出來並且按照gender
欄位進行分組,此外我們還想檢視其所有滿足條件同學的名字。
以下這樣操作會丟擲異常。
mysql> select gender,name from student where js > 80 group by gender;
ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'school.student.name' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
必須藉助group_concat()
函式來進行操作才能使我們的需求圓滿完成。
select gender, group_concat(name) from student where js > 80 group by gender;
+--------+--------------------+
| gender | group_concat(name) |
+--------+--------------------+
| male | Jack,Jason,Tom |
| famale | Bella |
+--------+--------------------+
分組模式
ONLY_FULL_GROUP_BY
要求select
中的欄位是在與group by
中使用的欄位
如果
group by
是主鍵或unique not null
時可以在select
中列出其他欄位
#檢視MySQL 5.7預設的sql_mode如下:
mysql> select @@global.sql_mode;
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
#設定sql_mole如下操作(我們可以去掉ONLY_FULL_GROUP_BY模式):
mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
聚合函式
聚合函式可以在where
執行後的所有語句中使用,比如having
,select
等。
聚合函式一般是同分組進行配套使用,以下是常用的聚合函式。
函式名 | 作用 |
---|---|
COUNT() | 對組內成員某一欄位求個數 |
MAX() | 對組內成員某一欄位求最大值 |
MIN() | 對組內成員某一欄位求最小值 |
AVG() | 對組內成員某一欄位求平均值 |
SUM() | 對組內成員某一欄位求和 |
注意:不使用分組,則預設為一組 |
以下示例將展示求每組的成績總和
select hoc_group, sum(js+html+css) from student group by hoc_group;
+-----------+-------------------+
| hoc_group | sum(js+html+css) |
+-----------+-------------------+
| fifth | 366 |
| first | 488 |
| fourth | 449 |
| second | 391 |
| third | 298 |
+-----------+-------------------+
以下示例將展示整個班級的平均成績及總成績(round()
用於四捨五入操作)
select round(avg(html+js+css)) as 平均分 ,sum(html+js+css) as 總分 from student;
+-----------+--------+
| 平均分 | 總分 |
+-----------+--------+
| 199 | 1992 |
+-----------+--------+
以下示例將展示列印出總科成績最高分數
select max(js+css+html) from student;
+------------------+
| max(js+css+html) |
+------------------+
| 273 |
+------------------+
以下示例將展示檢視本班有多少男生,多少女生
select gender, count(id) from student group by gender;
+--------+-----------+
| gender | count(id) |
+--------+-----------+
| male | 5 |
| famale | 5 |
+--------+-----------+
having
having
也可用於過濾操作
區別差異
執行優先順序從高到低:where
> group by
> having
where
發生在分組group by
之前,因而where
中可以有任意欄位,但是絕對不能使用聚合函式。
having
發生在分組group by
之後,因而having
中可以使用分組的欄位,無法直接取到其他欄位,可以使用聚合函式
示例演示
以下示例將展示使用having
過濾取出每組總分數大於400的小組
select hoc_group, sum(html+css+js) from student group by hoc_group having sum(html+css+js) > 400;
+-----------+------------------+
| hoc_group | sum(html+css+js) |
+-----------+------------------+
| first | 488 |
| fourth | 449 |
+-----------+------------------+
以下示例將展示使用having
過濾取出有處分的同學。(可以使用分組的欄位,但不能使用其他欄位)
select sanction, group_concat(name) from student group by sanction having sanction != "無";
+-----------+--------------------+
| sanction | group_concat(name) |
+-----------+--------------------+
| 大處分 | Dairis,Kyle,Ken |
| 小處分 | Bella |
+-----------+--------------------+
ordery by
ordery by
用於對查詢結果進行排序
預設的排序是按照主鍵進行排序的
asc
asc
用於升序排列,以下示例將展示按照每位同學的年齡進行升序排列,如果年齡相同則依照總成績進行升序排列。
select id, name, age, html+css+js as 總成績 from student order by age, html+css+js asc;
+----+--------+-----+-----------+
| id | name | age | 總成績 |
+----+--------+-----+-----------+
| 7 | Ken | 16 | 112 |
| 6 | Alice | 16 | 130 |
| 3 | Bella | 17 | 231 |
| 2 | Jack | 17 | 261 |
| 4 | Dairis | 18 | 186 |
| 1 | Yunya | 18 | 257 |
| 5 | Kyle | 19 | 115 |
| 10 | Fiona | 19 | 176 |
| 9 | Tom | 20 | 251 |
| 8 | Jason | 21 | 273 |
+----+--------+-----+-----------+
desc
desc
用於降序排列,以下示例將展示按照每位同學的年齡進行降序排列。
select id, name, age, html+css+js as 總成績 from student order by age desc;
+----+--------+-----+-----------+
| id | name | age | 總成績 |
+----+--------+-----+-----------+
| 8 | Jason | 21 | 273 |
| 9 | Tom | 20 | 251 |
| 5 | Kyle | 19 | 115 |
| 10 | Fiona | 19 | 176 |
| 1 | Yunya | 18 | 257 |
| 4 | Dairis | 18 | 186 |
| 2 | Jack | 17 | 261 |
| 3 | Bella | 17 | 231 |
| 6 | Alice | 16 | 130 |
| 7 | Ken | 16 | 112 |
+----+--------+-----+-----------+
limit
limit
用於控制顯示的條數
示例演示
按照總成績進行降序排序,只列印1-5
名。
select id, name, age, html+css+js as 總成績 from student order by html+css+js desc limit 5;
+----+-------+-----+-----------+
| id | name | age | 總成績 |
+----+-------+-----+-----------+
| 8 | Jason | 21 | 273 |
| 2 | Jack | 17 | 261 |
| 1 | Yunya | 18 | 257 |
| 9 | Tom | 20 | 251 |
| 3 | Bella | 17 | 231 |
+----+-------+-----+-----------+
按照總成績進行降序排序,只列印6-8
名。
select id, name, age, html+css+js as 總成績 from student order by html+css+js desc limit 5,3; # 從第五名開始,列印三條。 6,7,8
+----+--------+-----+-----------+
| id | name | age | 總成績 |
+----+--------+-----+-----------+
| 4 | Dairis | 18 | 186 |
| 10 | Fiona | 19 | 176 |
| 6 | Alice | 16 | 130 |
+----+--------+-----+-----------+