浮華褪盡,人比煙花寂寞…… ——張愛玲
一、表操作的補充
select * from 表名 where 列名 in (值1,值2,。。。);
查出對應值的數據。
1.1null 和 not null
使用null的時候:
當創建的表中有null時我們如果需要查詢出來null所對應的信息,需要用select * from 表名 where 字段名 is null;
mysql> create table v1(id int auto_increment primary key,
-> name varchar(32),email varchar(32))charset=utf8;
Query OK, 0 rows affected (0.70 sec)
mysql> insert into v1(email) values('xxx');
Query OK, 1 row affected (0.07 sec)
mysql> select * from v1;
+----+------+-------+
| id | name | email |
+----+------+-------+
| 1 | NULL | xxx |
+----+------+-------+
1 row in set (0.00 sec)
mysql> select * from v1 where name is null;
+----+------+-------+
| id | name | email |
+----+------+-------+
| 1 | NULL | xxx |
+----+------+-------+
1 row in set (0.01 sec)
mysql> select *from v1 where name='';
Empty set (0.00 sec)
使用null會降低數據的查詢效率,不推薦使用,在創建表的時候建議把值默認為空。
1.2使用not null的時候
mysql> create table v2(id int auto_increment primary key,
-> name varchar(32) not null default '',email varchar(32)not null default '')charset=utf8;
Query OK, 0 rows affected (0.44 sec)
mysql> insert into v2(email) values('xxx');
Query OK, 1 row affected (0.06 sec)
mysql> select *from v2 where name='';
+----+------+-------+
| id | name | email |
+----+------+-------+
| 1 | | xxx |
+----+------+-------+
1 row in set (0.00 sec)
二、單表的操作(import)
2.1分組
分組:將所標記的某個相同字段進行歸類,比如員工信息表的職位分組,或者按照性別進行分組等。
2.1.1聚合函數
max(列)求出列中的最大值
min(列)求出列中的最小值
sum(列)對列中的數據求和
count(列)對列中的數據計數
avg(列)對列中的數據計算平均數
例子見group by
2.1.2group by
用法:
select 聚合函數, 選取的字段 from employee group by 分組的字段;
group by 是分組的關鍵詞,group by 必須和聚合函數(count)一塊出現。count(字段名),按照條件對字段中的數據進行計數。
例子:
1.以性別為例, 進行分組, 統計一下男生和女生的人數是多少個。
mysql> create table employee(
-> id int not null unique auto_increment primary key,
-> name varchar(20) not null,
-> gender enum('male','female') not null default 'male',
-> age int(3) unsigned not null default 28,
-> hire_date date not null,
-> post varchar(50),
-> post_comment varchar(100),
-> salary double(15,2),
-> office int,
-> depart_id int
-> )charset=utf8;
Query OK, 0 rows affected (0.61 sec)
mysql> insert into employee(name,gender,age,hire_date,post,salary,office,depart_id) values
-> ('小張','male',73,'20140701','研發部',3500,401,1),
-> ('小李','male',28,'20121101','研發部',2100,401,1),
-> ('小趙','female',18,'20150411','研發部',18000,403,3),
-> ('歪歪','female',48,'20150311','銷售部',3000.13,402,2),
-> ('丫丫','female',38,'20101101','銷售部',2000.35,402,2),
-> ('丁丁','female',18,'20110312','銷售部',1000.37,402,2),
-> ('小明','male',28,'20160311','運營部',10000.13,403,3),
-> ('小華','male',18,'19970312','運營部',20000,403,3),
-> ('小王','female',18,'20130311','運營部',19000,403,3);
Query OK, 9 rows affected (0.09 sec)
Records: 9 Duplicates: 0 Warnings: 0
mysql> select count(id),gender from employee group by gender;
+-----------+--------+
| count(id) | gender |
+-----------+--------+
| 4 | male |
| 5 | female |
+-----------+--------+
2 rows in set (0.10 sec)
mysql> select gender,count(id) as total from employee group by gender;
#這里可以用as重命名顯示的列名
+--------+-------+
| gender | total |
+--------+-------+
| male | 4 |
| female | 5 |
+--------+-------+
2 rows in set (0.00 sec)
2.對部門進行分組, 求出每個部門年齡最大的那個人。
mysql> select depart_id , max(age) from employee group by depart_id;
+-----------+----------+
| depart_id | max(age) |
+-----------+----------+
| 1 | 73 |
| 2 | 48 |
| 3 | 28 |
+-----------+----------+
3 rows in set (0.04 sec)
3.對部門進行分組, 求出每個部門年齡求和。
mysql> select depart_id,sum(age) from employee group by depart_id;
+-----------+----------+
| depart_id | sum(age) |
+-----------+----------+
| 1 | 101 |
| 2 | 104 |
| 3 | 82 |
+-----------+----------+
3 rows in set (0.00 sec)
4.對部門進行分組, 求出每個部門年齡求平均數。
mysql> select depart_id,avg(age) from employee group by depart_id;
+-----------+----------+
| depart_id | avg(age) |
+-----------+----------+
| 1 | 50.5000 |
| 2 | 34.6667 |
| 3 | 20.5000 |
+-----------+----------+
3 rows in set (0.02 sec)
2.1.3having
對group by 之后的數據進行二次篩選
例子
5.對部門進行分組, 求出每個部門年齡求平均數,選出平均數最大的部門。
mysql> select depart_id,avg(age) from employee group by depart_id having avg(age)>35;
+-----------+----------+
| depart_id | avg(age) |
+-----------+----------+
| 1 | 50.5000 |
+-----------+----------+
1 row in set (0.00 sec)
mysql> select depart_id,avg(age)as pj from employee group by depart_id having pj>35;
+-----------+---------+
| depart_id | pj |
+-----------+---------+
| 1 | 50.5000 |
+-----------+---------+
1 row in set (0.00 sec)
2.1.4升序和降序
order by 字段名 asc(升序)desc(降序)
升序和降序可以同時使用如age desc, id asc;
表示: 先對age進行降序, 如果age有相同的行, 則對id進行升序。
例子
mysql> select * from employee order by age desc,id desc;
+----+--------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| id | name | gender | age | hire_date | post | post_comment | salary | office | depart_id |
+----+--------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| 1 | 小張 | male | 73 | 2014-07-01 | 研發部 | NULL | 3500.00 | 401 | 1 |
| 4 | 歪歪 | female | 48 | 2015-03-11 | 銷售部 | NULL | 3000.13 | 402 | 2 |
| 5 | 丫丫 | female | 38 | 2010-11-01 | 銷售部 | NULL | 2000.35 | 402 | 2 |
| 7 | 小明 | male | 28 | 2016-03-11 | 運營部 | NULL | 10000.13 | 403 | 3 |
| 2 | 小李 | male | 28 | 2012-11-01 | 研發部 | NULL | 2100.00 | 401 | 1 |
| 9 | 小王 | female | 18 | 2013-03-11 | 運營部 | NULL | 19000.00 | 403 | 3 |
| 8 | 小華 | male | 18 | 1997-03-12 | 運營部 | NULL | 20000.00 | 403 | 3 |
| 6 | 丁丁 | female | 18 | 2011-03-12 | 銷售部 | NULL | 1000.37 | 402 | 2 |
| 3 | 小趙 | female | 18 | 2015-04-11 | 研發部 | NULL | 18000.00 | 403 | 3 |
+----+--------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
9 rows in set (0.00 sec)
2.1.5limit限制輸出
limit offset ,size
limit 起始行索引,向下查詢的長度(索引為0代表第一行)
例子
mysql> select * from employee limit 0,3;
+----+--------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| id | name | gender | age | hire_date | post | post_comment | salary | office | depart_id |
+----+--------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| 1 | 小張 | male | 73 | 2014-07-01 | 研發部 | NULL | 3500.00 | 401 | 1 |
| 2 | 小李 | male | 28 | 2012-11-01 | 研發部 | NULL | 2100.00 | 401 | 1 |
| 3 | 小趙 | female | 18 | 2015-04-11 | 研發部 | NULL | 18000.00 | 403 | 3 |
+----+--------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
3 rows in set (0.00 sec)
2.1.6查詢表示需要遵循的順序(important)
select * from 表名 where 條件 group by 條件 having 條件 order by 條件 limit 條件;
where > group by > having > order by > limit
三、多表操作
外鍵
主關鍵字(primary key)是表中的一個或多個字段,它的值用於唯一地標識表中的某一條記錄。
公共關鍵字(Common Key)在關系數據庫中,關系之間的聯系是通過相容或相同的屬性或屬性組來表示的。如果兩個關系中具有相容或相同的屬性或屬性組,那么這個屬性或屬性組被稱為這兩個關系的公共關鍵字。
如果公共關鍵字在一個關系中是主關鍵字,那么這個公共關鍵字被稱為另一個關系的外鍵。由此可見,外鍵表示了兩個關系之間的相關聯系。以另一個關系的外鍵作主關鍵字的表被稱為主表,具有此外鍵的表被稱為主表的從表。外鍵又稱作外關鍵字。
使用外鍵的原因:
1.減少占用的內存空間
2.只需要修改主表的數據,從表的數據也會相應的跟着修改
3.1一對多
一對多指一個主表中的數據和從表中的數據是一對多的關系,如下例,一個部門可以有多個員工。
使用方法:
constraint 外鍵名 foreign key (被約束的字段) references 約束的表(約束的字段)
mysql> create table department(
-> id int auto_increment primary key,
-> name varchar(32) not null default '')
-> charset utf8;
Query OK, 0 rows affected (0.42 sec)
mysql> insert into department(name) values('研發部'),('運維部'),('前台部'),('小賣部');
Query OK, 4 rows affected (0.06 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> create table userinfo(id int auto_increment primary key,
-> name varchar(32) not null default '',
-> depart_id int not null default 1,
-> constraint fk_user_depart foreign key (depart_id) references department(id))
-> charset utf8;
Query OK, 0 rows affected (0.39 sec)
mysql> insert into userinfo (name,depart_id) values('xiaozhu',1),('xiaoyu',1),
-> ('laohe',2),('longge',2),('ludi',3),('xiaoguo',4);
Query OK, 6 rows affected (0.21 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select * from userinfo;
+----+---------+-----------+
| id | name | depart_id |
+----+---------+-----------+
| 1 | xiaozhu | 1 |
| 2 | xiaoyu | 1 |
| 3 | laohe | 2 |
| 4 | longge | 2 |
| 5 | ludi | 3 |
| 6 | xiaoguo | 4 |
+----+---------+-----------+
6 rows in set (0.00 sec)
mysql> select * from department;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 研發部 |
| 2 | 運維部 |
| 3 | 前台部 |
| 4 | 小賣部 |
+----+-----------+
4 rows in set (0.00 sec)
mysql> insert into userinfo(name,depart_id) values('xiaozhang',5);#depart_id受department.id的約束
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test2`.`userinfo`, CONSTRAINT `fk_user_depart` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`))
#聯表查詢
mysql> select userinfo.name as uname,department.name as dname from userinfo left
-> join department on depart_id = department.id;
+---------+-----------+
| uname | dname |
+---------+-----------+
| xiaozhu | 研發部 |
| xiaoyu | 研發部 |
| laohe | 運維部 |
| longge | 運維部 |
| ludi | 前台部 |
| xiaoguo | 小賣部 |
+---------+-----------+
6 rows in set (0.00 sec)
3.2多對多
多對多指當一個主表有多個從表時,從表之間的每個數據之間的關系就是多對多,如下圖,一個boy可以和多個girl約會,一個girl也可以和多個boy約會。
mysql> create table boy(id int auto_increment primary key,
-> bname varchar(32) not null default'')charset utf8;
Query OK, 0 rows affected (0.36 sec)
mysql> insert into boy(bname) values('zhangsan'),('lisi'),('wangwu');
Query OK, 3 rows affected (0.09 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> create table girl(id int auto_increment primary key,
-> gname varchar(32) not null default'')charset utf8;
Query OK, 0 rows affected (0.33 sec)
mysql> insert into girl(gname) values('xiaoli'),('xiaohua'),('xiaomei');
Query OK, 3 rows affected (0.06 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> create table boy_girl(id int auto_increment primary key,
-> bid int not null default 1,
-> gid int not null default 1,
-> constraint fk_boy_girl_boy foreign key(bid) references boy(id),
-> constraint fk_boy_girl_girl foreign key(gid) references girl(id)
-> )charset utf8;
Query OK, 0 rows affected (0.42 sec)
mysql> insert into boy_girl(bid,gid) values(1,1),(2,2),(3,3),(3,1),(2,1),(1,2);
Query OK, 6 rows affected (0.04 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select * from boy left join boy_girl on boy.id = boy_girl.bid left join girl
-> on girl.id = boy_girl.gid;
+----+----------+------+------+------+------+---------+
| id | bname | id | bid | gid | id | gname |
+----+----------+------+------+------+------+---------+
| 1 | zhangsan | 1 | 1 | 1 | 1 | xiaoli |
| 2 | lisi | 5 | 2 | 1 | 1 | xiaoli |
| 3 | wangwu | 4 | 3 | 1 | 1 | xiaoli |
| 1 | zhangsan | 6 | 1 | 2 | 2 | xiaohua |
| 2 | lisi | 2 | 2 | 2 | 2 | xiaohua |
| 3 | wangwu | 3 | 3 | 3 | 3 | xiaomei |
+----+----------+------+------+------+------+---------+
6 rows in set (0.03 sec)
mysql> select bname,gname from boy left join boy_girl on boy.id = boy_girl.bid
-> left join girl on girl.id = boy_girl.gid;
+----------+---------+
| bname | gname |
+----------+---------+
| zhangsan | xiaoli |
| lisi | xiaoli |
| wangwu | xiaoli |
| zhangsan | xiaohua |
| lisi | xiaohua |
| wangwu | xiaomei |
+----------+---------+
6 rows in set (0.00 sec)
3.3一對一
一對一指的是兩個表中的數據是一對一的關系,使用unique(字段名)來約束這種關系。如下例,由於工資屬於員工的敏感信息,用單獨的表去存儲,這時工資和員工信息就是一對一的關系。
mysql> create table priv(
-> id int auto_increment primary key,
-> salary int not null default 0,
-> uid int not null default 1,
-> constraint fk_priv_user foreign key (uid) references userinfo(id),
-> unique(uid)) charset=utf8;
Query OK, 0 rows affected (0.52 sec)
mysql> insert into priv(salary,uid) values (10000,1),(12000,2),(15000,3),(8000,4),(9000,5),(9900,6);
Query OK, 6 rows affected (0.16 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> select name,salary from userinfo left join priv on priv.uid = userinfo.id;
+---------+--------+
| name | salary |
+---------+--------+
| xiaozhu | 10000 |
| xiaoyu | 12000 |
| laohe | 15000 |
| longge | 8000 |
| ludi | 9000 |
| xiaoguo | 9900 |
+---------+--------+
6 rows in set (0.00 sec)
3.4多表聯查
多表聯查就是將多個有關系的表放在一起查,使用的語句有:
left join……on查詢時以左邊的數據為主
right join ……on查詢時以右邊的數據為主
mysql> insert into department(name) values('業務部');
Query OK, 1 row affected (0.12 sec)
mysql> select userinfo.name as uname,department.name as dname from userinfo left
-> join department on depart_id = department.id;
+---------+-----------+
| uname | dname |
+---------+-----------+
| xiaozhu | 研發部 |
| xiaoyu | 研發部 |
| laohe | 運維部 |
| longge | 運維部 |
| ludi | 前台部 |
| xiaoguo | 小賣部 |
+---------+-----------+
6 rows in set (0.00 sec)
mysql> select userinfo.name as uname,department.name as dname from userinfo right
-> join department on depart_id = department.id;
+---------+-----------+
| uname | dname |
+---------+-----------+
| xiaozhu | 研發部 |
| xiaoyu | 研發部 |
| laohe | 運維部 |
| longge | 運維部 |
| ludi | 前台部 |
| xiaoguo | 小賣部 |
| NULL | 業務部 |
+---------+-----------+
7 rows in set (0.00 sec)