【MYSQL】表的增删查改及具体应用(2)

表的增删查改

CURD:create retrieve update delete 增删查改

create :

 insert [INTO] table_name[(column [, column] ... )] values (value_list)[,(value_list)]...
 value_list : value [, value]...

单行全列插入可以不在table name 后指明column,但是我们建议不要省略。

多行插入可以用逗号隔开。

在unique 和 primary key 中,要求不能重复。 所以如果我们想修改主键/unique 的时候,可以直接

 insert into test (id, ...) values (1, ...) on duplicate key update id=1;

如果没冲突,那就执行前面的语句,一行被影响(新增一行)。如果冲突了,那就按update 后面进行修改。这时候会发现有两行被影响,这是因为冲突了是一次影响,冲突后的修改又是一次影响。

Replace

  • 主键或者唯一键没有冲突,就直接插入。

  • 主键或者唯一键冲突了,删除后再插入。

 REPLACE INTO students (sn, name) values (20001, 'amor');
 -- 1 row affected; 表中没有冲突数据,数据被插入
 -- 2 row affected; 表中有冲突数据,删除后又被重新插入

Retrieve

 SELECT 
 [DISTINCT] {* | {column [, column] ... }
 [FROM TALBE_NAME]
 [WHERE ...]
 [ORDER BY column [ASC | DESC], ...]
 LIMIT ...
  • 通常情况下不建议使用 * 进行全列查询。支持按列查询,将想要查询的列名 放在* 位置处即可。可以修改查询列的顺序。

  • select 在查询时,可以添加在表达式中不存在的字段,比如10 比如 10+ 10(应该是一个表达式,一个可以计算的式子),可以对字段进行乘除加减。就比如:

     select id, name, chinese+10 from test;
     -- 甚至还可以修改这个名字
     select id, name, chinese+english+math as 'total grade' from test;

    但是只是对筛选的结果做修改,不会修改原数据。

  • 选项 distinct ,表示去重

     select distinct math, id from exam_table;

    对整个的行进行去重,如果输出很多行,要全部都相同才会被筛选删去。

  • 排序 order by:

     select id, name, chinese+english+math as 'total grade' from test order by total grade; 
     -- 默认升序
     select id, name, chinese+english+math as 'total grade' from test order by total grade desc;
     -- 加desc 降序
     -- 加asc 升序(default)
     -- NULL 虽然不参与计算,但是在排序中如果升序会放到最前面。
     -- NULL 视为比任何值都笑,升序会出现在最上面。

    如果同时按照多个方法排序,会先按照最前面的排序,如果前面的字段相等,看后面,比如:

     select * from test order by math desc, chinese asc, english asc;
  • WHERE 条件:

    可以加 >= / > / = / <= / < 来限制输出条件

     select id,name,math from exam_result where math>=80;

    如果要找到NULL,不能用 = 比较,而是用<=> 比较 或者IS (NOT)NULL 来筛选。

  • where + between and 来查找在范围中的字段

     select name,math from exam_result where math bewtween 70 and 80;
     select name,math from exam_result where math >= 70 and math<=80;
     -- where 可以用 and / or / not
  • Where + in(option, ...) 来查找含有option 的字段

     select name,math from exam_result where math in(70,75,80,85);
     -- 等价于
     select name,math from exam_result where math = 70 or math = 75 or math = 80 or math =85;
  • where + like '' + % 代表任意多个字符, + _ 代表一个字符

     select name,math from exam_result where name like '孙%'; -- 所有姓孙的 
     select name,math from exam_result where name like '孙_'; -- 叫孙某的 就是孙一一 三个字的不算
  • select 的查询首先按照条件筛选数据,再按照要求计算数据,所以我们不能用起的别名来约束后面的的where 比如:

     select name, chinese+english+math as total_grade from exam_result wherechinese+english+math < 200
     -- 如果写成 : where total_grade < 200 就会不识别

    但是order by 就可以使用total_grade。

    这是因为排序时已经把数据全部都根据条件筛选完了。

    排序的本质就是计算。

    根据上述,要对于mysql 各个子句的执行顺序有刻意的练习。

    条件可以很多同时筛选,用( ) 加 and / or 分隔开。

  • limit n 代表只显示前n 行,顺序在最后。

  • offset n 配合limit m 使用,可以分页面显示。

  • 在select 中使用group by子句可以对指定列进行分组查询:

     select column1, column2, ... from table group by column;

    having 和group by 相配合,这里的用法与where 完全类似, 根本原因在于二者的执行位置的次序不同。

    • where 是过滤表中的数据的。(先where 筛选,再group by)

    • having 是过滤分组数据的。(先分组,先group by -> having)

    • 所以二者不会冲突,不过要按照他们执行的顺序来排列,如下:

       select deptno, avg(sal),count(*) from emp where deptno!=10 group by deptno havingavg(sal) < 2000;

      实际顺序是:where 过滤 -> 聚合语句 -> group by 分组 -> having

Update

 update exam_result set math=math+30 order by math+english+chinese asc limit 3;
 -- 将三科成绩倒数前三名的数学成绩加上30分

注意:更新全表的语句慎用!

delete

  • 删除表的数据:

     delete from table_name;

    删除表的数据,但是注意,删除之后,自增的序号仍然从原来的序号开始。比如自增的id 已经有了1,2,3,4,那么此时删除表的数据,再插入,id = 5;

  • 截断表:

     TRUNCATE [TABLE] table_name;

    操作慎用:

    只能对整个表操作,不能像delete 那样针对部分数据操作。

    实际上不对数据操作,所以比delete 更快,但是TRUNCATE 在删除数据的时候,并不经过真正的事物,所以无法回滚。

    会重置AUTO_INCREMENT 项。

delete 和 truncate 清空的区别:

日志:承担很大的功能要求,分为:

  • bin log:几乎所有的sql操作,mysqld 服务器都会给我们记录下来,该log 用来进行多主机同步,再增量备份

  • redo log :mysql 数据持久化 和crash-safe 功能(不怕崩溃,崩溃不影响mysql 的正常功能)

  • undo log:在事务中承担回滚的日志,数据操作恢复功能。

delete 清空会更新日志,truncate 清空不会更新日志。

复制表(去重)

比如我们先建立一个表,然后使用如下命令,就可以复制创建属性。

 create table newTable like oldTtable;

去重操作:

 select distinct * from oldTable; 
 -- 挑出来不重复的
 insert into newTable select distinct * from oldTable; 
 -- 直接插入

如果想保留去重后的表:

 rename table oldTable to oldTable_old;
 rename table newTable to oldTable;

聚合函数

将一个表中的多行进行聚合。

  • count,比如我们使用count 函数统计人数,可以使用:

     select count(*) 人数 from table_name;

    去重之后再统计:

     select count(distinct math) from exam_result;
  • sum

  • max/min

  • avg

  • 聚合函数和其他的字段显示可能不对应,现在不处理。

内置函数

内置函数不需要表,统一使用select 调用。

  • 日期函数:

    Current_date() 描述当前日期

    Current_time() 描述当前时间

    Current_timestamp() 描述当前时间戳

    Date(datetime) 返回datetime 参数的日期部分

    date_add(date, interval d_value_type) 在date 中添加日期或者时间,interval 后的数值单位可以是:year minute second day.

    Date_sub (date, interval d_value_type) 在date 中减去日期或者时间,interval 后的数值单位可以是:year minute second day.

    datediff(date1, date2) 描述两个日期的差,单位是天

    now(), 描述当前日期的时间。

    可以创建timestamp 的字段来完成自动更新时间的操作。

    可以使用 评论时间+ 2min > now() 来筛选两分钟内的评论。但是时间不能直接加两分钟,就需要使用date_add。

     select * from table_name where date_add(sendtime, interval 2 minute) >= now();
  • 字符串函数

    作用
    Charset(str) 返回字符串字符集
    concat(string2 [, ...]) 连接字符串
    instr(string, substring) 返回substring 在string 中出现的位置,没有则返回0
    Ucase(string2) 转换成大写
    lcase(string2) 转换成小写
    left(string2, length) 从string2 中的左边起取length 个字符
    length(string) string 的长度(字节数)
    replace(str, search_str, replace_str) 在str 中用replace_str 替换search_str
    strcmp(string1, string2) 逐字符比较两个字符串的大小
    substring(str, position [,length]) 从str 的position 开始,取length 个字符
    ltrim(string) / rtrim(string) / trim(string) 去掉前空格或者后空格

    举例:

    1. 获取emp 表的name 列字符集

     select charset(name) from EMP;
    1. 显示student 表中的信息,显示格式是:"XXX的语文是XXX分,数学XXX分,英语XXX分"

       select concat(name, '的语文是',chinese,'分,数学是',math,'分,英语是',english,'分') as'grade' from student;
  • 数学函数

    函数名称 描述
    abs(number) 绝对值函数
    Bin(decimal_number) 十进制转换二进制
    hex(decimal_number) 转换成十六进制
    Conv(number, from_base, to_base) 进制转换
    Ceiling(number) 向上取整 向正无穷的方向取整
    Floor(number) 向下取整
    Format(number, decimal_places) 格式化,保留小数位数
    Rand() 返回随机浮点数,范围[0.0 , 1.0)
    mod(number, denominator) 取模,求余
  • 其他函数

    名称 描述
    user() 哪个用户
    Md5(str) 形成定长摘要
    password() 形成密码
    ifnull(val1, val2) 有点像三目运算符,val1不为空,返回val1,val1 为空,返回val2

复合查询

  • 找出工资大于500 或者 岗位为MANAGER的雇员,同时满足名字首字母为J

     from emp where (sal > 500 or job ='MANAGER') and substring('ename,1,1);
     -- or
     ​
     from emp where (sal > 500 or job ='MANAGER') and ename like 'J%';
  • 显示工资最高的员工的名字和工作岗位

     select ename,job from emp where sal=(select max(sal) from emp);
  • 显示工资高于平均工资的员工信息;

     select * from emp where sal>(select avg(sal) from emp);
  • 显示平均工资低于2000 的部门号和他的平均工资

     select deptno, format(avg(sal) ,2)from emp group by deptno having avg(sal) < 2000;

    顺序:因为我们判断的是平均工资低于2000,平均工资是聚合条件,所以我们应该先分组然后判断,判断用having。

  • 显示每种岗位的雇员总数和平均工资。

     select job, count(*), avg(sal) from emp group by job;

多表查询

如果我们使用from 用逗号连接多个表,不加过滤条件得到的结果是的是两个表的笛卡尔积,意思是从第一张表中选出第一条记录,和第二张表中的每一行组合,然后从第一张表的第二条记录继续。

 select * from EMP, DEPT;

我们可以把多个表合成一表,所以在心中永远都是只有一张表。所以多表查询,本质上都是单表查询。

我们认为,所有select 查询出来的记录,都可以把它看作一个表。

  • 显示雇员名、雇员工资以及所在部门的名字

    我们知道雇员名和雇员的工资是在emp 表中,部门的名字在dept 表中,二者通过外键 deptno 联系起来。我们需要做的就是建立一张大表,如下。

     select * from emp, dept;
     ​
     +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+
     | empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno | deptno | dname      | loc      |
     +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+
     | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20|     40 | OPERATIONS | BOSTON   |
     | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20|     30 | SALES      | CHICAGO  |
     | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20|     20 | RESEARCH   | DALLAS   |
     | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20|     10 | ACCOUNTING | NEW YORK |
     | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30|     40 | OPERATIONS | BOSTON   |
     | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30|     30 | SALES      | CHICAGO  |
     | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30|     20 | RESEARCH   | DALLAS   |
     | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30|     10 | ACCOUNTING | NEW YORK |
     | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30|     40 | OPERATIONS | BOSTON   |
     | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30|     30 | SALES      | CHICAGO  |
     | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30|     20 | RESEARCH   | DALLAS   |
     | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30|     10 | ACCOUNTING | NEW YORK |
     | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20|     40 | OPERATIONS | BOSTON   |
     | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20|     30 | SALES      | CHICAGO  |
     | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20|     20 | RESEARCH   | DALLAS   |
     | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20|     10 | ACCOUNTING | NEW YORK |
     | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30|     40 | OPERATIONS | BOSTON   |
     | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30|     30 | SALES      | CHICAGO  |
     | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30|     20 | RESEARCH   | DALLAS   |
     | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30|     10 | ACCOUNTING | NEW YORK |
     | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30|     40 | OPERATIONS | BOSTON   |
     | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30|     30 | SALES      | CHICAGO  |
     | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30|     20 | RESEARCH   | DALLAS   |
     | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30|     10 | ACCOUNTING | NEW YORK |
     | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10|     40 | OPERATIONS | BOSTON   |
     | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10|     30 | SALES      | CHICAGO  |
     | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10|     20 | RESEARCH   | DALLAS   |
     | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10|     10 | ACCOUNTING | NEW YORK |
     | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20|     40 | OPERATIONS | BOSTON   |
     | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20|     30 | SALES      | CHICAGO  |
     | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20|     20 | RESEARCH   | DALLAS   |
     | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20|     10 | ACCOUNTING | NEW YORK |
     | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10|     40 | OPERATIONS | BOSTON   |
     | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10|     30 | SALES      | CHICAGO  |
     | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10|     20 | RESEARCH   | DALLAS   |
     | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10|     10 | ACCOUNTING | NEW YORK |
     | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30|     40 | OPERATIONS | BOSTON   |
     | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30|     30 | SALES      | CHICAGO  |
     | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30|     20 | RESEARCH   | DALLAS   |
     | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30|     10 | ACCOUNTING | NEW YORK |
     | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20|     40 | OPERATIONS | BOSTON   |
     | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20|     30 | SALES      | CHICAGO  |
     | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20|     20 | RESEARCH   | DALLAS   |
     | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20|     10 | ACCOUNTING | NEW YORK |
     | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30|     40 | OPERATIONS | BOSTON   |
     | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30|     30 | SALES      | CHICAGO  |
     | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30|     20 | RESEARCH   | DALLAS   |
     | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30|     10 | ACCOUNTING | NEW YORK |
     | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20|     40 | OPERATIONS | BOSTON   |
     | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20|     30 | SALES      | CHICAGO  |
     | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20|     20 | RESEARCH   | DALLAS   |
     | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20|     10 | ACCOUNTING | NEW YORK |
     | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10|     40 | OPERATIONS | BOSTON   |
     | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10|     30 | SALES      | CHICAGO  |
     | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10|     20 | RESEARCH   | DALLAS   |
     | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10|     10 | ACCOUNTING | NEW YORK |
     +--------+--------+-----------+------+---------------------+---------+---------+--------+--------+------------+----------+

    但是可以发现结果中 deptno 和后面的deptno 如果不想等,就根本毫无意义。所以我们需要做的就是加上一个限制条件,不过限制条件如果写 where deptno = deptno,mysql 根本无法识别,那需要加上前缀:

     select * from emp,dept where emp.deptno=dept.deptno;

    我们要的是雇员名,雇员工资以及所在部门的名字:

     select ename,sal,dname from emp, dept where emp.deptno=dept.deptno;
  • 显示各个员工的姓名、工资及工资级别

     select * from emp,salgrade where emp.sal > salgrade.losal and emp.sal < salgrade.hisalorder by salgrade.grade;

    但是因为现在 sal 和 hisal losal 都不重复,所以可以不用带上emp. salgrade.

  • 显示员工FORD 上级领导的编号和姓名

     select empno, ename from emp where empno=(select mgr from emp where ename='FORD');
     select leader.ename, leader.empno from emp worker,emp leader where worker.ename='FORD'and worker.mgr=leader.empno;

子查询

单行字查询是指的是字查询只返回单列,单行数据;多行字查询指的是返回单列多行数据,都是针对单列而言。

  • in关键字:用来查询其中的一员

    查询和10号部门的工作岗位相同的雇员名字,岗位,工资,部门号,但是不包含10号自己的。

     select ename,job,sal,deptno from emp where job in (select distinct job from emp wheredeptno=10) and deptno!=10;
  • all 关键字:我比你们所有字段都要XXX

    显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号。

     select ename,sal,deptno from emp where sal>(select max(distinct sal) from emp wheredeptno=30);
     ​
     --2--
     select ename,sal,deptno from emp where sal> all(select distinct sal from emp wheredeptno=30);
  • any 关键字:比任意一个字段XXX

    显示工资比部门30 的任意员工的工资高的员工的姓名、工资和部门号(包括自己部门的员工)。

     select ename,sal,deptno from emp where sal > any(select sal from emp where deptno=30)order by sal;

多列子查询指的是查询返回多个列数据的子查询语句。

  • 查询和SMITH 的部门和岗位完全相同的所有雇员,不含SMITH 本人。

     select * from emp where (ename != 'SMITH') and (job=(select job from emp where ename='SMITH')) and (deptno=(select deptno from emp where ename='SMITH'));
     ​
     --2--
     select * from emp where (ename != 'SMITH') and (deptno,job)=(select deptno,job from emp where ename='SMITH');

用from

因为我们说可以把一条select 语句看成一个表,所以我们可以在from 后加select语句。

  • 显示每个高于自己部门平均工资的员工的姓名,部门,工资和平均工资。

     --平均工资
     select deptno, avg(sal) avg from emp group by deptno;
     --高于自己部门的平均工资:
     select ename,emp.deptno,sal,avg from emp,(select deptno, avg(sal) avg from emp group bydeptno) avg_dept where emp.deptno=avg_dept.deptno and emp.sal>avg_dept.avg;
  • 查找每个部门工资最高的人的姓名、工资、部门和最高工资。

     -- 每个部门的最高工资
     select deptno, max(sal) from emp group by deptno;
     -- 找出最高工资的人的姓名和工资部门
     select ename, sal, emp.deptno, max_sal from emp, (select deptno, max(sal) max_sal fromemp group by deptno) maxsal_dept where emp.deptno=maxsal_dept.deptno and sal=max_sal;
  • 显示每个部门的信息(部门名、编号、地址)和人员数量

     -- 部门名dname 部门编号deptno 部门地址loc 都在 dept表中
     -- 人员的数量可以使用count 统计,在dept中。
     -- 二表通过相同的deptno 来进行统一。
     select dname, dept.deptno, loc, count from dept, (select deptno, count(*) count fromemp group by deptno) cnt_tb where dept.deptno=cnt_tb.deptno;

合并查询

  • union 取并集,会自动去重

     select ... union
     select ...;
  • union all 取并集,不会去重

表的内外连接

表的连接分为内连和外连。

内连接

内连接实际上就是利用where 子句对两种表形成的笛卡尔积进行筛选,我们前面学习的查询都是内连接,也是在开发过程中使用的最多的连接查询。

 select 字段 from table1 inner join table2 on 连接条件 and 其他条件;
  • 显示SMITH 的名字和部门名称

     select * from emp, dept where emp.deptno=dept.deptno and ename='SMITH';
     select * from emp inner join dept on emp.deptno=dept.deptno where ename='SMITH';

外连接

  • 左外连接: 将inner 换成left

     select * from table1 left join table2 on ...

    就是把 table1 放到 table2 的后面,如果找得到对应的table2 的数据,就拼到table1 的右边,否则就拼NULL

  • 右外连接:inner 换成right

示例

  • 列出部门名称和这些部门的员工信息和没有员工的部门

     select * from dept left join emp on dept.deptno=emp.deptno;

你可能感兴趣的:(mysql,数据库)