单表查询

一 单表查询的语法

#查询数据的本质:mysql会到你本地的硬盘上找到对应的文件,然后打开文件,按照你的查询条件来找出你需要的数据。下面是完整的一个单表查询的语法select * from,这个select * 指的是要查询所有字段的数据。SELECT distinct 字段1,字段2... FROM 库名.表名 #from后面是说从库的某个表中去找数据,mysql会去找到这个库对应的文件夹下去找到你表名对应的那个数据文件,找不到就直接报错了,找到了就继续后面的操作WHERE 条件       #从表中找符合条件的数据记录,where后面跟的是你的查询条件GROUP BY field(字段)   #分组HAVING 筛选      #过滤,过滤之后执行select后面的字段筛选,就是说我要确定一下需要哪个字段的数据,你查询的字段数据进行去重,然后在进行下面的操作ORDER BY field(字段) #将结果按照后面的字段进行排序LIMIT 限制条数    #将最后的结果加一个限制条数,就是说我要过滤或者说限制查询出来的数据记录的条数

二 关键字的执行优先级

重点中的重点:关键字的执行优先级
from
where
group by
having
select
distinct
order by
limit

1.找到表:from
2.拿着where指定的约束条件,去文件/表中取出一条条记录
3.将取出的一条条记录进行分组group by,如果没有group by,则整体作为一组
4.将分组的结果进行having过滤
5.执行select
6.去重
7.将结果按条件排序:order by
8.限制结果的显示条数

简单查询

避免重复DISTINCT

mysql> SELECT DISTINCT post FROM employee;
+-----------------------------------------+
| post                                    |
+-----------------------------------------+
| teacher                                 |
| sale                                    |
| operation                               |
+-----------------------------------------+mysql> select distinct post,salary from employee;
+-----------------------------------------+------------+
| post                                    | salary     |
+-----------------------------------------+------------+
| teacher                                 | 1000000.31 |
| teacher                                 |    8300.00 |
| teacher                                 |    3500.00 |
| teacher                                 |    2100.00 |
| teacher                                 |    9000.00 |
| teacher                                 |   30000.00 |
| teacher                                 |   10000.00 |
| sale                                    |    3000.13 |
| sale                                    |    2000.35 |
| sale                                    |    1000.37 |
| sale                                    |    3000.29 |
| sale                                    |    4000.33 |
| operation                               |   10000.13 |
| operation                               |   20000.00 |
| operation                               |   19000.00 |
| operation                               |   18000.00 |
| operation                               |   17000.00 |
+-----------------------------------------+------------+
因为这个去重条件变成了post和salary两个字段的数据,只有他俩合起来是一个重复记录的时候才会去重

通过四则运算查询
加 减 乘 除
select id*3 from employee;
自定义显示格式,自己规定查询结果的显示格式
concat() 函数用于连接字符串

mysql> select concat('姓名:',name,' 年薪:',salary*12) as sum_salary from employee;
+------------------------------------+
| sum_salary                         |
+------------------------------------+
| 姓名:111 年薪:87603.96            |
| 姓名:333 年薪:12000003.72         |
| 姓名:admin 年薪:99600.00         |
| 姓名:root 年薪:42000.00         |
+------------------------------------+

concat_ws() 第一个参数为分隔符来进行字符串拼接

mysql> select concat_ws(':',name,salary*12) as sum_salary from employee;
+----------------------+
| sum_salary           |
+----------------------+
| 111:87603.96        |
| 333:12000003.72     |
| admin:99600.00     |
| root:42000.00     |
+----------------------+

四 WHERE 约束

where语句中可以使用:

  1. 比较运算符:> < >= <= <> !=
  2. between 80 and 100 值在80到100之间
  3. in(80,90,100) 值是80或90或100
  4. like ‘egon%’
    pattern可以是%或_,
    %表示任意多字符
    _表示一个字符
  5. 逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not
#1:单条件查询SELECT name FROM employeeWHERE post='sale';  #注意优先级,我们说where的优先级是不是比select要高啊,所以我们的顺序是先找到这个employee表,然后按照post='sale'的条件,然后去表里面select数据#2:多条件查询SELECT name,salary FROM employee WHERE post='teacher' AND salary>10000;#3:关键字BETWEEN AND 写的是一个区间SELECT name,salary FROM employee WHERE salary BETWEEN 10000 AND 20000; #就是salary>=10000 and salary<=20000的数据SELECT name,salary FROM employee WHERE salary NOT BETWEEN 10000 AND 20000; #加个not,就是不在这个区间内,薪资小于10000的或者薪资大于20000的,注意没有等于,#4:关键字IS NULL(判断某个字段是否为NULL不能用等号,需要用IS) 判断null只能用isSELECT name,post_comment FROM employee WHERE post_comment IS NULL;SELECT name,post_comment FROM employee WHERE post_comment IS NOT NULL;SELECT name,post_comment FROM employee WHERE post_comment=''; 注意''是空字符串,不是null,两个是不同的东西,null是啥也没有,''是空的字符串的意思,是一种数据类型,null是另外一种数据类型ps:执行update employee set post_comment='' where id=2;再用上条查看,就会有结果了#5:关键字IN集合查询SELECT name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ; #这样写是不是太麻烦了,写一大堆的or,下面我们用in这个简单的写法来搞SELECT name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ;SELECT name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ;#6:关键字LIKE模糊查询,模糊匹配,可以结合通配符来使用通配符’%’  #匹配任意所有字符SELECT * FROM employee WHERE name LIKE 'eg%';通配符’_’  #匹配任意一个字符   SELECT * FROM employee WHERE name LIKE 'al__'; #注意我这里写的两个_,用1个的话,匹配不到alex,因为al后面还有两个字符ex。

五 分组查询:GROUP BY

#1、首先明确一点:分组发生在where之后,即分组是基于where之后得到的记录而进行的#2、分组指的是:将所有记录按照某个相同字段进行归类,比如针对员工信息表的职位分组,或者按照性别进行分组等#3、为何要分组呢?是因为我们有时候会需要以组为单位来统计一些数据或者进行一些计算的,对不对,比方说下面的几个例子取每个部门的最高工资  取每个部门的员工数取男人数和女人数  小窍门:‘每’这个字后面的字段,就是我们分组的依据,只是个小窍门,但是不能表示所有的情况,看上面第三个分组,没有'每'字,这个就需要我们通过语句来自行判断分组依据了我们能用id进行分组吗,能,但是id是不是重复度很低啊,基本没有重复啊,对不对,这样的字段适合做分组的依据吗?不适合,对不对,依据性别分组行不行,当然行,因为性别我们知道,是不是就两种啊,也可能有三种是吧,这个重复度很高,对不对,分组来查的时候才有更好的意义#4、大前提:可以按照任意字段分组,但是分组完毕后,比如group by post,只能查看post字段,如果想查看组内信息,需要借助于聚合函数#注意一点,在查询语句里面select 字段 from 表,这几项是必须要有的,其他的什么where、group by等等都是可有可无的

ONLY_FULL_GROUP_BY

#查看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#!!!注意
ONLY_FULL_GROUP_BY的语义就是确定select target list中的所有列的值都是明确语义,简单的说来,在ONLY_FULL_GROUP_BY模式下,target list中的值要么是来自于聚集函数的结果,要么是来自于group by list中的表达式的值。#设置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';测试
mysql> select @@global.sql_mode;
+-------------------+
| @@global.sql_mode |
+-------------------+
|                   |
+-------------------+
1 row in set (0.00 sec)mysql> select * from emp group by post;
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
| id | name | sex    | age | hire_date  | post                       | post_comment | salary     | office | depart_id |
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
| 14 | 张野 | male   |  28 | 2016-03-11 | operation                  | NULL         |   10000.13 |    403 |         3 |
|  9 | 歪歪 | female |  48 | 2015-03-11 | sale                       | NULL         |    3000.13 |    402 |         2 |
|  2 | alex | male   |  78 | 2015-03-02 | teacher                    | NULL         | 1000000.31 |    401 |         1 |
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
4 rows in set (0.00 sec)#由于没有设置ONLY_FULL_GROUP_BY,于是也可以有结果,默认都是组内的第一条记录,但其实这是没有意义的mysql> set global sql_mode='ONLY_FULL_GROUP_BY';
Query OK, 0 rows affected (0.00 sec)mysql> quit #设置成功后,一定要退出,然后重新登录方可生效
Byemysql> use db1;
Database changed
mysql> select * from emp group by post; #报错
ERROR 1055 (42000): 'db1.emp.id' isn't in GROUP BY  #意思是告诉你,你select后面取的字段必须在你的group by后面的字段里面才行mysql> select post,count(id) from emp group by post; #只能查看分组依据和使用聚合函数
+----------------------------+-----------+
| post                       | count(id) |
+----------------------------+-----------+
| operation                  |         5 |
| sale                       |         5 |
| teacher                    |
+----------------------------+-----------+
4 rows in set (0.00 sec)因为一般分组之后,我们再考虑其中一条数据就没有什么意义了,所以一般我们都会在这种模式下进行分组,下面我们在看看group by,下面的内容

GROUP BY

单独使用GROUP BY关键字分组SELECT post FROM employee GROUP BY post;注意:我们按照post字段分组,那么select查询的字段只能是post,想要获取组内的其他相关信息,需要借助函数GROUP BY关键字和GROUP_CONCAT()函数一起使用,比如说我想按部门分组,每个组有哪些员工,都显示出来,怎么搞SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;#按照岗位分组,并查看组内所有成员名,通过逗号拼接在一起SELECT post,GROUP_CONCAT(name,':',salary) as emp_members FROM employee GROUP BY post;GROUP BY一般都会与聚合函数一起使用,聚合是什么意思:聚合就是将分组的数据聚集到一起,合并起来搞事情,拿到一个最后的结果select post,count(id) as count from employee group by post;#按照岗位分组,并查看每个组有多少人,每个人都有唯一的id号,我count是计算一下分组之后每组有多少的id记录,通过这个id记录我就知道每个组有多少人了关于集合函数,mysql提供了以下几种聚合函数:count、max、min、avg、sum等,上面的group_concat也算是一个聚合函数了,做字符串拼接的操作** 如果我们用设置了unique约束的字段作为分组的依据,则每一条记录自成一组,这种分组没有意义
多条记录之间的某个字段值相同,该字段通常用来作为分组的依据

修改模式的方法(修改成严格模式)

模式设置和修改(以解决上述问题为例):方式一:先执行select @@sql_mode,复制查询出来的值并将其中的NO_ZERO_IN_DATE,NO_ZERO_DATE删除,然后执行set sql_mode = '修改后的值'或者set session sql_mode='修改后的值';,例如:set session sql_mode='STRICT_TRANS_TABLES';改为严格模式 #session可以不用写此方法只在当前会话中生效,关闭当前会话就不生效了。方式二:先执行select @@global.sql_mode,复制查询出来的值并将其中的NO_ZERO_IN_DATE,NO_ZERO_DATE删除,然后执行set global sql_mode = '修改后的值'。此方法在当前服务中生效,重新MySQL服务后失效方法三:在mysql的安装目录下,或my.cnf文件(windows系统是my.ini文件),新增 sql_mode = STRICT_TRANS_TABLES添加my.cnf如下:
[mysqld]            sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER

GROUP_CONCAT()

mysql> SELECT post,GROUP_CONCAT(name,':',salary) as emp_members FROM employee GROUP BY post;
+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------+
| post                                    | emp_members                                                                                                          |
+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------+
| operation                               | 程咬铁:17000.00,程咬铜:18000.00,程咬银:19000.00,程咬金:20000.00,张野:10000.13                                        |
| sale                                    | 格格:4000.33,星星:3000.29,丁丁:1000.37,丫丫:2000.35,歪歪:3000.13                                                     |
| teacher                                 | 成龙:10000.00,lilianjie:30000.00,angelbaby:9000.00,tomcat:2100.00,root:3500.00,admin:8300.00,aaa:1000000.31   |
+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------+

聚合函数

#强调:聚合函数聚合的是组的内容,若是没有分组,则默认一组示例:SELECT COUNT(*) FROM employee;  #count是统计个数用的SELECT COUNT(*) FROM employee WHERE depart_id=1;  #后面跟where条件的意思是统计一下满足depart_id=1这个的所有记录的个数SELECT MAX(salary) FROM employee;  #max()统计分组后每组的最大值,这里没有写group by,那么就是统计整个表中所有记录中薪资最大的,薪资的值SELECT MIN(salary) FROM employee;SELECT AVG(salary) FROM employee;SELECT SUM(salary) FROM employee;SELECT SUM(salary) FROM employee WHERE depart_id=3;

六 HAVING过滤

having的语法格式和where是一模一样的,只不过having是在分组之后进行的进一步的过滤,where不能使用聚合函数,having是可以使用聚合函数的
执行优先级从高到低:where > group by > having

  1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数。

  2. Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,having是可以使用聚合函数

七 order by 排序

按单列排序默认是升序排列SELECT * FROM employee ORDER BY salary; 升序SELECT * FROM employee ORDER BY salary ASC;降序SELECT * FROM employee ORDER BY salary DESC; 按多列排序:先按照age升序,如果年纪相同,则按照薪资降序SELECT * from employeeORDER BY age, #注意排序的条件用逗号分隔salary DESC;

八 限制查询的记录数:LIMIT(尽量不用,效率低)

可以用来分页显示

示例:#取出工资最高的前三位SELECT * FROM employee ORDER BY salary DESC LIMIT 3;                    #默认初始位置为0,从第一条开始顺序取出三条 SELECT * FROM employee ORDER BY salary DESCLIMIT 0,5; #从第0开始,即先查询出第一条,然后包含这一条在内往后查5条 SELECT * FROM employee ORDER BY salary DESCLIMIT 5,5; #从第5开始,即先查询出第6条,然后包含这一条在内往后查5条

九 使用正则表达式查询

#之前我们用like做模糊匹配,只有%和_,局限性比较强,所以我们说一个正则,之前我们是不是学过正则匹配,你之前学的正则表达式都可以用,正则是通用的
SELECT * FROM employee WHERE name REGEXP '^ale';SELECT * FROM employee WHERE name REGEXP 'on$';SELECT * FROM employee WHERE name REGEXP 'm{2}';小结:对字符串匹配的方式
WHERE name = 'egon';
WHERE name LIKE 'yua%';
WHERE name REGEXP 'on$';

多表查询

一 多表连接查询

重点:外链接语法
SELECT 字段列表
  FROM 表1 INNER|LEFT|RIGHT JOIN 表2
  ON 表1.字段 = 表二.字段;

inner 默认join
内连接:只连接匹配的行

#我们要找的数据就是员工表里面dep_id字段的值和部门表里面id字段的值能对应上的那些数据啊,所以你看下面的写法:
mysql> select * from employee,department where employee.dep_id=department.id;
+----+-----------+--------+------+--------+------+--------------+
| id | name      | sex    | age  | dep_id | id   | name         |
+----+-----------+--------+------+--------+------+--------------+
|  1 | yangmi      | male   |   18 |    200 |  200 | 技术         |
|  2 | zangziyi      | female |   48 |    201 |  201 | 人力资源     |
|  3 | xietingfeng   | male   |   38 |    201 |  201 | 人力资源     |
|  4 | liukaiwei   | female |   28 |    202 |  202 | 销售         |
|  5 | liziwen | male   |   18 |    200 |  200 | 技术         |
+----+-----------+--------+------+--------+------+--------------+
5 rows in set (0.14 sec)
拿到了我们想要的结果。但是你看,我们左表employee表中的dep_id为204的那个数据没有了,右表department表的id为203的数据没有了,因为我们现在要的就是两表能对应上的数据一起查出来,那个204和203双方对应不上。再看一个需求,我要查出技术部的员工的名字
mysql> select name from employee,department where employee.dep_id=department.id and department.name='技术';
ERROR 1052 (23000): Column 'name' in field list is ambiguous
记住,表.name就不会报上面的错了
上面直接就报错了,因为select后面直接写的name,在两个表合并起来的表中,是有两个name字段的,直接写name是不行的,要加上表名,再看:
mysql> select employee.name from employee,department where employee.dep_id=department.id and department.name='技术';
+-----------+
| name      |
+-----------+
| yangmi      |
| liziwen |
+-----------+
2 rows in set (0.09 sec)
结果就没问题了

左连接:优先显示左表全部记录

以左表为准,即找出所有员工信息,当然包括没有部门的员工
本质就是:在内连接的基础上增加左边有右边没有的结果  #注意语法:
mysql> select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
+----+------------+--------------+
| id | name       | depart_name  |
+----+------------+--------------+
|  1 | yangmi       | 技术         |
|  5 | zangziyi     | 技术         |
|  2 | xietingfeng  | 人力资源     |
|  3 | liukaiwei    | 人力资源     |
|  4 | zhaowei      | 销售         |
|  6 | jingliwen    | NULL         |
+----+------------+--------------+mysql> select employee.id,employee.name,department.name as depart_name from employee left join department on employee.depart_id = department.id;
+----+------------+-------------+
| id | name       | depart_name |
+----+------------+-------------+
|  1 | egon       | 教学        |
|  2 | alex       | 教学        |
|  3 | wupeiqi    | 教学        |
|  4 | yuanhao    | 教学        |
|  5 | liwenzhou  | 教学        |
|  6 | jingliyang | 教学        |
|  7 | jinxin     | 教学        |
|  8 | 成龙       | 教学        |
|  9 | 歪歪       | 销售        |
| 10 | 丫丫       | 销售        |
| 11 | 丁丁       | 销售        |
| 12 | 星星       | 销售        |
| 13 | 格格       | 销售        |
| 14 | 张野       | 运营        |
| 15 | 程咬金     | 运营        |
| 16 | 程咬银     | 运营        |
| 17 | 程咬铜     | 运营        |
| 18 | 程咬铁     | 运营        |
+----+------------+-------------+

右连接:优先实现右表的全部记录

右连接
以右表为准,即找出所有部门信息,包括没有员工的部门
本质就是:在内连接的基础上增加右边有左边没有的结果
mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
+------+-----------+--------------+
| id   | name      | depart_name  |
+------+-----------+--------------+
|    1 | egon      | 技术         |
|    2 | alex      | 人力资源     |
|    3 | wupeiqi   | 人力资源     |
|    4 | yuanhao   | 销售         |
|    5 | liwenzhou | 技术         |
| NULL | NULL      | 运营         |
+------+-----------+--------------+

全外连接:显示左右两个表全部记录

全外连接:在内连接的基础上增加左边有右边没有的和右边有左边没有的结果
注意:mysql不支持全外连接 full JOIN
强调:mysql可以使用此种方式间接实现全外连接
select * from employee left join department on employee.dep_id = department.id
union
select * from employee right join department on employee.dep_id = department.id
;
#查看结果
+------+------------+--------+------+--------+------+--------------+
| id   | name       | sex    | age  | dep_id | id   | name         |
+------+------------+--------+------+--------+------+--------------+
|    1 | egon       | male   |   18 |    200 |  200 | 技术         |
|    5 | liwenzhou  | male   |   18 |    200 |  200 | 技术         |
|    2 | alex       | female |   48 |    201 |  201 | 人力资源     |
|    3 | wupeiqi    | male   |   38 |    201 |  201 | 人力资源     |
|    4 | yuanhao    | female |   28 |    202 |  202 | 销售         |
|    6 | jingliyang | female |   18 |    204 | NULL | NULL         |
| NULL | NULL       | NULL   | NULL |   NULL |  203 | 运营         |
+------+------------+--------+------+--------+------+--------------+注意 union与union all的区别:union会去掉相同的纪录,因为union all是left join 和right join合并,所以有重复的记录,通过union就将重复的记录去重了。mysql> select * from employee left join department on employee.depart_id = department.id-> union-> select * from employee right join department on employee.depart_id = department.id-> ;
+------+------------+--------+------+------------+-----------------------------------------+--------------+------------+--------+-----------+------+--------+
| id   | name       | sex    | age  | hire_date  | post                                    | post_comment | salary     | office | depart_id | id   | name   |
+------+------------+--------+------+------------+-----------------------------------------+--------------+------------+--------+-----------+------+--------+
|    1 | egon       | male   |   18 | 2017-03-01 | 老男孩驻沙河办事处外交大使              | NULL         |    7300.33 |    401 |         1 |    1 | 教学   |
|    2 | alex       | male   |   78 | 2015-03-02 | teacher                                 | NULL         | 1000000.31 |    401 |         1 |    1 | 教学   |
|    3 | wupeiqi    | male   |   81 | 2013-03-05 | teacher                                 | NULL         |    8300.00 |    401 |         1 |    1 | 教学   |
|    4 | yuanhao    | male   |   73 | 2014-07-01 | teacher                                 | NULL         |    3500.00 |    401 |         1 |    1 | 教学   |
|    5 | liwenzhou  | male   |   28 | 2012-11-01 | teacher                                 | NULL         |    2100.00 |    401 |         1 |    1 | 教学   |
|    6 | jingliyang | female |   18 | 2011-02-11 | teacher                                 | NULL         |    9000.00 |    401 |         1 |    1 | 教学   |
|    7 | jinxin     | male   |   18 | 1900-03-01 | teacher                                 | NULL         |   30000.00 |    401 |         1 |    1 | 教学   |
|    8 | 成龙       | male   |   48 | 2010-11-11 | teacher                                 | NULL         |   10000.00 |    401 |         1 |    1 | 教学   |
|    9 | 歪歪       | female |   48 | 2015-03-11 | sale                                    | NULL         |    3000.13 |    402 |         2 |    2 | 销售   |
|   10 | 丫丫       | female |   38 | 2010-11-01 | sale                                    | NULL         |    2000.35 |    402 |         2 |    2 | 销售   |
|   11 | 丁丁       | female |   18 | 2011-03-12 | sale                                    | NULL         |    1000.37 |    402 |         2 |    2 | 销售   |
|   12 | 星星       | female |   18 | 2016-05-13 | sale                                    | NULL         |    3000.29 |    402 |         2 |    2 | 销售   |
|   13 | 格格       | female |   28 | 2017-01-27 | sale                                    | NULL         |    4000.33 |    402 |         2 |    2 | 销售   |
|   14 | 张野       | male   |   28 | 2016-03-11 | operation                               | NULL         |   10000.13 |    403 |         3 |    3 | 运营   |
|   15 | 程咬金     | male   |   18 | 1997-03-12 | operation                               | NULL         |   20000.00 |    403 |         3 |    3 | 运营   |
|   16 | 程咬银     | female |   18 | 2013-03-11 | operation                               | NULL         |   19000.00 |    403 |         3 |    3 | 运营   |
|   17 | 程咬铜     | male   |   18 | 2015-04-11 | operation                               | NULL         |   18000.00 |    403 |         3 |    3 | 运营   |
|   18 | 程咬铁     | female |   18 | 2014-05-12 | operation                               | NULL         |   17000.00 |    403 |         3 |    3 | 运营   |
+------+------------+--------+------+------------+-----------------------------------------+--------------+------------+--------+-----------+------+--------+

符合条件连接查询(连表之后执行其它判断语句)

#示例1:以内连接的方式查询employee和department表,并且employee表中的age字段值必须大于25,即找出年龄大于25岁的员工以及员工所在的部门
select employee.name,department.name from employee inner join departmenton employee.dep_id = department.idwhere age > 25;#示例2:以内连接的方式查询employee和department表,并且以age字段的升序方式显示
select employee.id,employee.name,employee.age,department.name from employee,departmentwhere employee.dep_id = department.idand age > 25order by age asc;

子查询
  子查询其实就是将你的一个查询结果用括号括起来,这个结果也是一张表,就可以将它交给另外一个sql语句,作为它的一个查询依据来进行操作。

#首先从部门表里面找到技术部门对应的id
mysql> select id from department where name='技术';
+------+
| id   |
+------+
|  200 |
+------+
1 row in set (0.00 sec)#那我们把上面的查询结果用括号括起来,它就表示一条id=200的数据,然后我们通过员工表来查询dep_id=这条数据作为条件来查询员工的name
mysql> select name from employee where dep_id = (select id from department where name='技术');
+-----------+
| name      |
+-----------+
| egon      |
| liwenzhou |
+-----------+
2 rows in set (0.00 sec)
上面这些就是子查询的一个思路,解决一个问题,再解决另外一个问题,你子查询里面可不可以是多个表的查询结果,当然可以,然后再通过这个结果作为依据来进行过滤,子查询:
1:子查询是将一个查询语句嵌套在另一个查询语句中。
2:内层查询语句的查询结果,可以为外层查询语句提供查询条件。
3:子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字
4:还可以包含比较运算符:= 、 !=、> 、<等

带IN关键字的子查询

#查询员工平均年龄在25岁以上的部门名,可以用连表,也可以用子查询,我们用子查询来搞一下
select id,name from departmentwhere id in (select dep_id from employee group by dep_id having avg(age) > 25);
#连表来搞一下上面这个需求
select department.name from department inner join employee on department.id=employee.dep_id group by department.name having avg(age)>25;
总结:子查询的思路和解决问题一样,先解决一个然后拿着这个的结果再去解决另外一个问题,连表的思路是先将两个表关联在一起,然后在进行group by啊过滤啊等等操作,两者的思路是不一样的#查看技术部员工姓名
select name from employeewhere dep_id in (select id from department where name='技术');#查看不足1人的部门名(子查询得到的是有人的部门id)
select name from department where id not in (select distinct dep_id from employee);

带比较运算符的子查询

#比较运算符:=、!=、>、>=、<、<=、<>
#查询大于所有人平均年龄的员工名与年龄
mysql> select name,age from emp where age > (select avg(age) from emp);
+---------+------+
| name | age |
+---------+------+
| alex | 48 |
| wupeiqi | 38 |
+---------+------+
2 rows in set (0.00 sec)#查询大于部门内平均年龄的员工名、年龄
select t1.name,t1.age from emp t1
inner join
(select dep_id,avg(age) avg_age from emp group by dep_id) t2
on t1.dep_id = t2.dep_id
where t1.age > t2.avg_age;

带EXISTS关键字的子查询
  EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。而是返回一个真假值。True或False
  当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询。还可以写not exists,和exists的效果就是反的

#department表中存在dept_id=203,Ture
mysql> select * from employee->     where exists  ->         (select id from department where id=200);
+----+------------+--------+------+--------+
| id | name       | sex    | age  | dep_id |
+----+------------+--------+------+--------+
|  1 | egon       | male   |   18 |    200 |
|  2 | alex       | female |   48 |    201 |
|  3 | wupeiqi    | male   |   38 |    201 |
|  4 | yuanhao    | female |   28 |    202 |
|  5 | liwenzhou  | male   |   18 |    200 |
|  6 | jingliyang | female |   18 |    204 |
+----+------------+--------+------+--------+#department表中存在dept_id=205,False
mysql> select * from employee->     where exists->         (select id from department where id=204);
Empty set (0.00 sec)

超难24道mysql题
数据

#创建表及插入记录
CREATE TABLE class (cid int(11) NOT NULL AUTO_INCREMENT,caption varchar(32) NOT NULL,PRIMARY KEY (cid)
) ENGINE=InnoDB CHARSET=utf8;INSERT INTO class VALUES
(1, '三年二班'),
(2, '三年三班'),
(3, '一年二班'),
(4, '二年九班');CREATE TABLE course(cid int(11) NOT NULL AUTO_INCREMENT,cname varchar(32) NOT NULL,teacher_id int(11) NOT NULL,PRIMARY KEY (cid),KEY fk_course_teacher (teacher_id),CONSTRAINT fk_course_teacher FOREIGN KEY (teacher_id) REFERENCES teacher (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO course VALUES
(1, '生物', 1),
(2, '物理', 2),
(3, '体育', 3),
(4, '美术', 2);CREATE TABLE score (sid int(11) NOT NULL AUTO_INCREMENT,student_id int(11) NOT NULL,course_id int(11) NOT NULL,num int(11) NOT NULL,PRIMARY KEY (sid),KEY fk_score_student (student_id),KEY fk_score_course (course_id),CONSTRAINT fk_score_course FOREIGN KEY (course_id) REFERENCES course (cid),CONSTRAINT fk_score_student FOREIGN KEY (student_id) REFERENCES student(sid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO score VALUES
(1, 1, 1, 10),
(2, 1, 2, 9),
(5, 1, 4, 66),
(6, 2, 1, 8),
(8, 2, 3, 68),
(9, 2, 4, 99),
(10, 3, 1, 77),
(11, 3, 2, 66),
(12, 3, 3, 87),
(13, 3, 4, 99),
(14, 4, 1, 79),
(15, 4, 2, 11),
(16, 4, 3, 67),
(17, 4, 4, 100),
(18, 5, 1, 79),
(19, 5, 2, 11),
(20, 5, 3, 67),
(21, 5, 4, 100),
(22, 6, 1, 9),
(23, 6, 2, 100),
(24, 6, 3, 67),
(25, 6, 4, 100),
(26, 7, 1, 9),
(27, 7, 2, 100),
(28, 7, 3, 67),
(29, 7, 4, 88),
(30, 8, 1, 9),
(31, 8, 2, 100),
(32, 8, 3, 67),
(33, 8, 4, 88),
(34, 9, 1, 91),
(35, 9, 2, 88),
(36, 9, 3, 67),
(37, 9, 4, 22),
(38, 10, 1, 90),
(39, 10, 2, 77),
(40, 10, 3, 43),
(41, 10, 4, 87),
(42, 11, 1, 90),
(43, 11, 2, 77),
(44, 11, 3, 43),
(45, 11, 4, 87),
(46, 12, 1, 90),
(47, 12, 2, 77),
(48, 12, 3, 43),
(49, 12, 4, 87),
(52, 13, 3, 87);CREATE TABLE student(sid int(11) NOT NULL AUTO_INCREMENT,gender char(1) NOT NULL,class_id int(11) NOT NULL,sname varchar(32) NOT NULL,PRIMARY KEY (sid),KEY fk_class (class_id),CONSTRAINT fk_class FOREIGN KEY (class_id) REFERENCES class (cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO student VALUES
(1, '男', 1, '理解'),
(2, '女', 1, '钢蛋'),
(3, '男', 1, '张三'),
(4, '男', 1, '张一'),
(5, '女', 1, '张二'),
(6, '男', 1, '张四'),
(7, '女', 2, '铁锤'),
(8, '男', 2, '李三'),
(9, '男', 2, '李一'),
(10, '女', 2, '李二'),
(11, '男', 2, '李四'),
(12, '女', 3, '如花'),
(13, '男', 3, '刘三'),
(14, '男', 3, '刘一'),
(15, '女', 3, '刘二'),
(16, '男', 3, '刘四');CREATE TABLE teacher(tid int(11) NOT NULL AUTO_INCREMENT,tname varchar(32) NOT NULL,PRIMARY KEY (tid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO teacher VALUES
(1, '张磊老师'),
(2, '李平老师'),
(3, '刘海燕老师'),
(4, '朱云海老师'),
(5, '李杰老师');

24道题

1、查询所有的课程的名称以及对应的任课老师姓名2、查询学生表中男女生各有多少人3、查询物理成绩等于100的学生的姓名4、查询平均成绩大于八十分的同学的姓名和平均成绩5、查询所有学生的学号,姓名,选课数,总成绩6、 查询姓李老师的个数7、 查询没有报李平老师课的学生姓名8、 查询物理课程比生物课程高的学生的学号9、 查询没有同时选修物理课程和体育课程的学生姓名10、查询挂科超过两门(包括两门)的学生姓名和班级11 、查询选修了所有课程的学生姓名12、查询李平老师教的课程的所有成绩记录13、查询全部学生都选修了的课程号和课程名14、查询每门课程被选修的次数15、查询之选修了一门课程的学生姓名和学号16、查询所有学生考出的成绩并按从高到低排序(成绩去重)17、查询平均成绩大于85的学生姓名和平均成绩18、查询生物成绩不及格的学生姓名和对应生物分数19、查询在所有选修了李平老师课程的学生中,这些课程(李平老师的课程,不是所有课程)平均成绩最高的学生姓名20、查询每门课程成绩最好的前两名学生姓名21、查询不同课程但成绩相同的学号,课程号,成绩22、查询没学过“叶平”老师课程的学生姓名以及选修的课程名称;23、查询所有选修了学号为1的同学选修过的一门或者多门课程的同学学号和姓名;24、任课最多的老师中学生单科成绩最高的学生姓名

Mysql单表查询和多表查询相关推荐

  1. mysql 单标递归_MYSQL递归树查询的实现

    ​    在oracle中我们可以使用connect by prior 函数来实现组织树表递归的查询,但是在mysql中却没有该方法,为了能够使用该方法我们就得自己创建函数来实现该组织树的递归查询.以 ...

  2. MySQL单表多字段模糊查询

    今天工作时遇到一个功能问题:就是输入关键字搜索的字段不只一个字段,比如 我输入: 超天才 ,需要检索出 包含这个关键字的 name . company.job等多个字段.在网上查询了一会就找到了答案. ...

  3. MySQL之单表查询、多表查询(一)

    阅读目录 一.单表查询: ①.基本语法执行顺序 ②.where约束条件的使用 ③.group by 分组 ④.having (类似于where,但是必须在group by语句后使用) ⑤.distin ...

  4. mysql为何500w拆表_【mysql】MySQL 单表500W+数据,查询超时,如何优化呢?

    1.问题描述: MySQL 数据库,单表 `im_data_record`,查询超时(30s) 表结构如下图: 表索引如下图: 查询语句如下: SELECT `record_global_id`, ` ...

  5. MYSQL 单表一对多查询,将多条记录合并成一条记录

    MYSQL 单表一对多查询,将多条记录合并成一条记录 一.描述: 在MySQL 5.6环境下,应工作需求:将一个表中多条某个相同字段的其他字段合并(不太会表达,有点绕,直接上图) 想要达到的效果: 实 ...

  6. mysql 单表多级查询_mysql单表与多表查询

    单表查询 """ 增: insert [into] [数据库名.]表名[(字段1[, ..., 字段n])] values (数据1[, ..., 数据n])[, ... ...

  7. mysql单表查询详解

    文章目录 一.单表查询 1.1 创建数据库 1.2 单表查询 1.2.1 查询所有字段 1.2.2 使用通配符*查询所有字段 1.2.3 查询指定字段 1.2.4 去重distinct的使用 1.2. ...

  8. mysql同张表关联多次查询_MySQL多次单表查询和多表联合查询

    Tip:不建议执行三张表以上的多表联合查询 对数据量不大的应用来说,多表联合查询开发高效,但是多表联合查询在表数据量大,并且没有索引的时候,如果进行笛卡儿积,那数据量会非常大,sql执行效率会非常低 ...

  9. mysql单表查询实例_MySQL简单查询详解-单表查询

    MySQL简单查询详解-单表查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查询的执行路径 一条SQL查询语句的执行过程大致如下图所示: 1>.客户端和服务端通过my ...

最新文章

  1. CUDA学习(十五)
  2. 使用putty上传文件
  3. boost的multi_index性能测试
  4. windows环境 wildfly-10.1.0.Final 安装、配置、部署
  5. 2Python全栈之路系列之MysQl基本数据类型
  6. 你知道荷兰旗问题吗?
  7. Rust LeetCode 练习:929 Unique Email Addresses
  8. Mysql 中的SSL 连接
  9. Flex 得到一个对象的所有属性
  10. Unity调用Android类方法
  11. java 需求文档_java 项目需求文档要怎么写?
  12. 基于NFC的Android读写软件,基于Android的NFC商场助手软件的设计与实现
  13. 小米手机计算机usb连接,小米5手机怎么连接电脑 USB调试方法教程
  14. 如何注册Google Voice账号(电话号码)
  15. 大前端之js导入导出
  16. 如何为firefox安装视频播放器
  17. 阿里云ECS部署L2TP/IPSEC,访问服务器内网
  18. 我(作为一名开发者)所犯过的错误
  19. Android蓝牙打印小票,仿美团外卖小票打印
  20. CentOS7环境下 人大金仓kes86数据库安装过程

热门文章

  1. zabbix-agent配置详解
  2. 未来战争 计算机病毒,对计算机病毒攻击武器的新思考
  3. 怎样取消老毛桃软件赞助商---只需在输入框中输入老毛桃官网网址“laomaotao.org”...
  4. 智能电视和网络电视有什么区别
  5. 算法导论第十五章:动态规划(一)
  6. 首页 干货教程 大数据动向 大数据应用 数据可视化 数据分析 投资并购 企业专区 注册 登录 随机森林入门攻略(内含R、Python代码)
  7. 程序员如何从技术岗转为技术管理层?
  8. 【天光学术】民法学论文:从税收法定主义看我国税收立法之不足【开题报告 硕士研究生毕业论文】
  9. 北理工计算机学院新闻,北理工计算机学院召开物联网工程本科专业建设研讨会...
  10. 内网搭建maven私库