MySQL數據庫3分組與單表、多表查詢


浮華褪盡,人比煙花寂寞…… ——張愛玲

一、表操作的補充

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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM