单表多表操作 联表查询

Posted mcoming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单表多表操作 联表查询相关的知识,希望对你有一定的参考价值。

一、单表操作

1. 分组——> group by

  • 分组指的是:将所有表记录按照某个相同字段进行归类

  • 用法:

    • select 聚合函数,选取的字段 from 表名 group by 选择分组的字段 having 条件

    • 聚合函数:count/sum/max/min/avg

    • having:表示对group by之后的数据,进行再一次的筛选

    • 注意:group by必须和集合函数一起使用。

    • where 条件语句和groupby分组语句的先后顺序:
      where > group by > having(*********)

  • 实例:

    mysql> select depart_id,avg(age) from employee group by depart_id ;
                  +-----------+----------+
                  | depart_id | avg(age) |
                  +-----------+----------+
                  |         1 |  45.2500 |
                  |         2 |  30.0000 |
                  |         3 |  20.0000 |
                  +-----------+----------+
                  3 rows in set (0.00 sec)
    
                  mysql> select depart_id,avg(age) from employee group by depart_id having avg(age) > 35;
                  +-----------+----------+
                  | depart_id | avg(age) |
                  +-----------+----------+
                  |         1 |  45.2500 |
                  +-----------+----------+
                  1 row in set (0.00 sec)

2. 排序——> order by

  • order by对查询的结果进行排序

  • 用法:

    • order by 字段名 asc/desc ,其中asc默认的表示升序排序,desc表示降序排序
    • 如果对多个字段进行排序,如 order by age desc , id asc,则先对age进行降序排序,如果排完序记录中有相同的age时,再把有相同的这些行按id升序排序。

3. 分页——> limit

  • 用法:
    • limit 参数1 , 参数2 。参数1表示行索引,从该行开始,表记录第第一行数据的索引是0,往下递增,参数2表示取多少行。

4. 总结(很重要)

  • 以上高级用法的使用顺序是:

    • select * from 表名 where 条件 group by 条件 having 条件 order by 条件 limit 条件;

    • where > group by > having > order by > limit

二、多表操作

1. 外键

  • 使用外键的原因:

    • 减少占用的空间
    • 只需要修改一次原表中的数据 ,其余有对应外键的表中的数据就会相应的修改。
  • 使用方法:

    constraint 外键名 foreign key (被约束的字段) references 约束的表(约束的字段)

2. 一对多(很常见类型)

  • 实例:

    create table department(
                      id int auto_increment primary key,
                      name varchar(32) not null default ''
                  )charset utf8;
    
                  insert into department (name) values ('研发部');
                  insert into department (name) values ('运维部');
                  insert into department (name) values ('前台部');
                  insert into department (name) values ('小卖部');
    
                  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;
    
                  insert into userinfo (name, depart_id) values ('zekai', 1);
                  insert into userinfo (name, depart_id) values ('xxx', 2);
                  insert into userinfo (name, depart_id) values ('zekai1', 3);
                  insert into userinfo (name, depart_id) values ('zekai2', 4);
                  insert into userinfo (name, depart_id) values ('zekai3', 1);
                  insert into userinfo (name, depart_id) values ('zekai4', 2);
                  insert into userinfo (name, depart_id) values ('zekai4', 5);

3. 多对多(常见类型)

  • 实例:

    create table boy (
                      id int auto_increment primary key,
                      bname varchar(32) not null default ''
                  )charset utf8;
    
                  insert into boy (bname) values ('zhangsan'),('lisi'),('zhaoliu');
    
                  create table girl (
                      id int auto_increment primary key,
                      gname varchar(32) not null default ''
                  )charset utf8;
                  insert into girl (gname) values ('cuihua'),('gangdan'),('jianguo');
    
                  create table boy2girl (
                      id int auto_increment primary key,
                      bid int not null default 1,
                      gid int not null default 1,
    
                      constraint fk_boy2girl_boy foreign key (bid) references boy(id),
                      constraint fk_boy2girl_girl foreign key (gid) references girl(id)
                  )charset utf8;
    
                  insert into boy2girl (bid, gid) values (1,1),(1,2),(2,3),(3,3),(2,2);
    
    
                  select * from boy left join  boy2girl on boy.id = boy2girl.bid left join girl on girl.id=boy2girl.gid;
    
                  mysql> select * from boy left join  boy2girl on boy.id = boy2girl.bid left join girl on girl.id=boy2girl.gid;
                  +----+----------+------+------+------+------+---------+
                  | id | bname    | id   | bid  | gid  | id   | gname   |
                  +----+----------+------+------+------+------+---------+
                  |  1 | zhangsan |    1 |    1 |    1 |    1 | cuihua  |
                  |  1 | zhangsan |    2 |    1 |    2 |    2 | gangdan |
                  |  2 | lisi     |    5 |    2 |    2 |    2 | gangdan |
                  |  2 | lisi     |    3 |    2 |    3 |    3 | jianguo |
                  |  3 | zhaoliu  |    4 |    3 |    3 |    3 | jianguo |
                  +----+----------+------+------+------+------+---------+
                  5 rows in set (0.00 sec)
    
                  mysql> select bname, gname from boy left join  boy2girl on boy.id = boy2girl.bid left join girl on girl.id=boy2girl.gid;
                  +----------+---------+
                  | bname    | gname   |
                  +----------+---------+
                  | zhangsan | cuihua  |
                  | zhangsan | gangdan |
                  | lisi     | gangdan |
                  | lisi     | jianguo |
                  | zhaoliu  | jianguo |
                  +----------+---------+
                  5 rows in set (0.00 sec)
    
                  mysql> select bname, gname from boy left join  boy2girl on boy.id = boy2girl.bid left join girl on girl.id=boy2girl.gid where bname='zhangsan';
                  +----------+---------+
                  | bname    | gname   |
                  +----------+---------+
                  | zhangsan | cuihua  |
                  | zhangsan | gangdan |
                  +----------+---------+
                  2 rows in set (0.02 sec)

4. 一对一(不常见类型)

  • 实例:

    user :
                      id   name  age  
                      1    zekai  18   
                      2    zhangsan 23  
                      3    xxxx   19   
    
                  由于salary是比较敏感的字段,因此我们需要将此字段单独拆出来, 变成一张独立的表
    
                  private:
    
                      id  salary   uid  (外键 + unique)
                      1    5000     1
                      2    6000     2
                      3    3000     3
    
    
                  create table user (
                      id int auto_increment primary key,
                      name varchar(32) not null default ''
                  )charset=utf8;
    
                  insert into user (name) values ('zhangsan'),('zekai'),('kkk');
    
    
                  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 user(id),
                      unique(uid)
                  )charset=utf8;
    
                  insert into priv (salary, uid) values (2000, 1);
                  insert into priv (salary, uid) values (2800, 2);
                  insert into priv (salary, uid) values (3000, 3);
    
                  insert into priv (salary, uid) values (6000, 1);
                  ERROR 1062 (23000): Duplicate entry '1' for key 'uid'

三、多表联查

1. 左连接——>left join...on

  • 表示已left左边的表为主,会把左边的表中的信息全部显示,被join的表按照左边的表的数据一一对应显示。

  • 实例

    # 原表
    mysql> select * from department;
              +----+--------+
              | id | name   |
              +----+--------+
              |  1 | 研发部 |
              |  2 | 运维部 |
              |  3 | 前台部 |
              |  4 | 小卖部 |
              +----+--------+
              4 rows in set (0.07 sec)
    
              mysql> select * from userinfo;
              +----+--------+-----------+
              | id | name   | depart_id |
              +----+--------+-----------+
              |  1 | zekai  |         1 |
              |  2 | xxx    |         2 |
              |  3 | zekai1 |         3 |
              |  4 | zekai2 |         4 |
              |  5 | zekai3 |         1 |
              |  6 | zekai4 |         2 |
              +----+--------+-----------+
              6 rows in set (0.00 sec)
    
    # 联表查询:            
    
    # 错误写法                
    mysql> select name  from userinfo left join department on depart_id = department.id;
    ERROR 1052 (23000): Column 'name' in field list is ambiguous
    
    # 正确写法
    mysql> select userinfo.name as uname, department.name as dname  from userinfo left join department on depart_id = department.id;
    
    # 查询结果
                  +--------+--------+
                  | uname  | dname  |
                  +--------+--------+
                  | zekai  | 研发部 |
                  | zekai3 | 研发部 |
                  | xxx    | 运维部 |
                  | zekai4 | 运维部 |
                  | zekai1 | 前台部 |
                  | zekai2 | 小卖部 |
                  +--------+--------+
                  6 rows in set (0.00 sec)

2. 右连接——>right join...on

  • 表示已right右边的表为主,会把右边的表中的信息全部显示,被join的表按照右边的表的数据一一对应显示。

  • 实例:

    mysql> insert into department (name) values ('财务部');
                  Query OK, 1 row affected (0.04 sec)
    
                  mysql>
                  mysql> select * from department;                     );
                  +----+--------+
                  | id | name   |
                  +----+--------+
                  |  1 | 研发部 |
                  |  2 | 运维部 |
                  |  3 | 前台部 |
                  |  4 | 小卖部 |
                  |  5 | 财务部 |
                  +----+--------+
                  5 rows in set (0.00 sec)
    
                  mysql> select * from userinfo;
                  +----+--------+-----------+
                  | id | name   | depart_id |
                  +----+--------+-----------+
                  |  1 | zekai  |         1 |
                  |  2 | xxx    |         2 |
                  |  3 | zekai1 |         3 |
                  |  4 | zekai2 |         4 |
                  |  5 | zekai3 |         1 |
                  |  6 | zekai4 |         2 |
                  +----+--------+-----------+
                  6 rows in set (0.00 sec)
    
                  mysql> select userinfo.name as uname, department.name as dname  from userinfo left join department on depart_id = department.id;
                  +--------+--------+
                  | uname  | dname  |
                  +--------+--------+
                  | zekai  | 研发部 |
                  | zekai3 | 研发部 |
                  | xxx    | 运维部 |
                  | zekai4 | 运维部 |
                  | zekai1 | 前台部 |
                  | zekai2 | 小卖部 |
                  +--------+--------+
                  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  |
                  +--------+--------+
                  | zekai  | 研发部 |
                  | zekai3 | 研发部 |
                  | xxx    | 运维部 |
                  | zekai4 | 运维部 |
                  | zekai1 | 前台部 |
                  | zekai2 | 小卖部 |
                  | NULL   | 财务部 |
                  +--------+--------+
                  7 rows in set (0.00 sec)

3. 内连接——>inner join...on

  • 实例:

    mysql> select * from department inner join userinfo on department.id=userinfo.depart_id;
                  +----+--------+----+--------+-----------+
                  | id | name   | id | name   | depart_id |
                  +----+--------+----+--------+-----------+
                  |  1 | 研发部 |  1 | zekai  |         1 |
                  |  1 | 研发部 |  5 | zekai3 |         1 |
                  |  2 | 运维部 |  2 | xxx    |         2 |
                  |  2 | 运维部 |  6 | zekai4 |         2 |
                  |  3 | 前台部 |  3 | zekai1 |         3 |
                  |  4 | 小卖部 |  4 | zekai2 |         4 |
                  +----+--------+----+--------+-----------+
                  6 rows in set (0.00 sec)

以上是关于单表多表操作 联表查询的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 基础之 单表多表联查

Django模型层:单表多表操作F与Q查询

Mysql单表多表查询

mysql单表多表查询

数据库之表查询,单表多表,子查询

单表多表操作