单表查询

2.where语句

where 语句在from [join on ]之后执行

ps:where后面不能直接跟聚合函数!,不使用where默认选择所有记录

where语句的作用是根据条件进行过滤记录,选择符合条件的记录
可以使用

  • 比较运算符:><>= <= <> !=
  • between 80 and 100 值在10到20之间
  • in(80,90,100) 值是10或20或30
  • like 'egon%' 模式可以是%或_,%表示任意多字符,_表示一个字符
  • 逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not

查询语法举例

#1:单条件查询
SELECT name FROM employee
    WHERE post='sale';

#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;

SELECT name,salary FROM employee 
    WHERE salary NOT BETWEEN 10000 AND 20000;

#4:关键字IS NULL(判断某个字段是否为NULL不能用等号,需要用IS)
SELECT 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,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 ;

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__';
        
select id,name,age from employee where id > 7;
select name,post,salary from employee where post='teacher' and salary > 8000;
select name,salary from employee where salary >= 20000 and salary <= 30000;
select name,salary from employee where salary between 20000 and 30000; #区间
select name,salary from employee where salary < 20000 or salary > 30000;
select name,salary from employee where salary not between 20000 and 30000;
select * from employee where age = 73 or age = 81 or age = 28;
select * from employee where age in (73,81,28);
select * from employee where post_comment is Null;
select * from employee where post_comment is not Null;
select * from employee where name like "jin%"; --%任意n个字符
select * from employee where name like "jin___"; -- %___任意几个字符,可以多写几个__


3.group by

group by 在where语句之后执行

  • group by 是按照某个字段进行分组,将该字段相同的值的记录放在一起作为一组进行归类,比如针对员工信息表的职位分组,或者按照性别进行分组等。 没有group by则默认整体为一组
  • 为何要分组呢?比如要取每个部门的最高工资、取每个部门的员工数、取男人数和女人数这些需求,就需要分组处理。
    小窍门:‘每’这个字后面的字段,就是我们分组的依据
  • ps:可以按照任意字段分组,但是分组完毕后,比如group by post,只能查看post字段,如果想查看组内信息,需要借助于聚合函数,这是由于mySQL的sql_mode一般为ONLY_FULL_GROUP_BY,只允许查询分组的字段,但是可以通过设置参数,使select语句能够查询其他字段,但是不推荐这么使用

设置sql_mode,针对5.7版本(了解)

#查看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'; 

group by 使用示例

如果我们用unique的字段作为分组的依据,则每一条记录自成一组,这种分组没有意义;应该用多条记录之间的某个字段值相同的字段,该字段通常用来作为分组的依据。

单独使用GROUP BY关键字分组

select distinct post from employee where id < 3 group by post;

GROUP BY关键字和GROUP_CONCAT()函数一起使用

SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;--按照岗位分组,并查看组内成员名
SELECT post,GROUP_CONCAT(name) as emp_members FROM employee GROUP BY post;
-- GROUP_CONCAT(name) 将该组name字段所有的值结合在一起显示

GROUP BY与聚合函数一起使用

select post,count(id) as count from employee group by post; -- 按照岗位分组,并查看每个组有多少人


4.聚合函数

ps:

聚合函数聚合的是组的内容,若是没有分组,按照执行优先顺序,默认为整体一组后,在相关语句方可使用,例如

select count(id) from employee;

常用的聚合函数

SELECT COUNT(*) FROM employee; -- count()统计个数
SELECT COUNT(*) FROM employee WHERE depart_id=1;
SELECT MAX(salary) FROM employee; -- max()求最大值
SELECT MIN(salary) FROM employee; -- min()求最小值
SELECT AVG(salary) FROM employee; -- avg()求平均值
SELECT SUM(salary) FROM employee; -- sum()求和
SELECT SUM(salary) FROM employee WHERE depart_id=3;

注!如下针对5.6版本默认的sql_mode配置能够让分组后直接查询其他字段信息,需要修改成严格模式

select * from employee group by post; 
#每个组只取了一个!需要修改一下相关配置,严格模式
mysql> set global sql_mode="ONLY_FULL_GROUP_BY"; 
#设置了要重新登录一下

select * from employee group by post;
#设置之后,这句话就不灵了!分组之后,只能取分组的字段,以及每个组聚合结果
select post from employee group by post;

查询示例

select post,count(id) as emp_count from employee group by post;--每个职位有多少个员工,以组为单位进行统计
select post,max(salary) as emp_count from employee group by post;
select post,min(salary) as emp_count from employee group by post;
select post,avg(salary) as emp_count from employee group by post;
select post,sum(age) as emp_count from employee group by post;
select max(salary) from employee;--没有group by则默认整体算作一组
select post,group_concat(name) from employee group by post; #group_concat 查看所有员工的名字


5.having

having 在 group by 之后执行

having 的功能是在分组之后进行过滤,而判断过滤的条件只能取分组字段或者聚合函数,不能直接拿其他字段进行判断;同理,执行where语句的时候还没有执行分组,所以where语句里面不能使用聚合函数。

如下是不能成立的

select post,avg(salary) from employee group by post having id > 3; -- having 不能直接使用其他字段

查询小练习
查询各岗位内包含的员工的岗位名、岗位内包含员工名字、个数
查询各岗位内包含的员工个数小于2的岗位名、岗位内包含员工名字、个数
查询各岗位平均薪资大于10000的岗位名、平均工资
查询各岗位平均薪资大于10000且小于20000的岗位名、平均工资

select post,group_concat(name),count(id) from employee group by post;
select post,group_concat(name),count(id) from employee group by post having count(id) < 2;
select post,avg(salary) from employee group by post having avg(salary) > 10000;
select post,avg(salary) from employee group by post having avg(salary) between 10000 and 20000;



6.order by

order by 语句发生在distinct语句之后,也就是分完组,选择了符合条件的记录,组成了一个新的虚拟表(组分完了,而且合并成新的一个表了,千万不要将此时的状态和分组时的状态搞混淆

order by 语句的作用是将查询到的结果按照相应的字段进行升序或者降序排序显示,默认为升序。

select * from employee order by salary;
select * from employee order by salary asc;  -- asc 表示按照升序排序
select * from employee order by salary desc; -- desc 表示按照降序排序

order by 语句可以同时有多个排序规则,当字段出现相同值,会按照后面指定的规则进行排序!

select * from employee order by age asc,id desc;--先按照age升序排,如果age相同则按照id降序排

小试牛刀

  1. 查询所有员工信息,先按照age升序排序,如果age相同则按照hire_date降序排序
  2. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资升序排列
  3. 查询各岗位平均薪资大于10000的岗位名、平均工资,结果按平均薪资降序排列
  4. 查询各岗位薪资大于10000且高于该工资至少有两位员工的岗位名、员工数,结果按员工数降序排列

select * from employee order by age asc,hire_date desc;

select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) asc;

select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) desc;

select distinct post,count(id) as emp_count from employee
    where salary > 1000
    group by post
    having count(id) > 1
    order by emp_count desc


7. limit

limit 语句在order by 之后执行,用于限制显示的记录条数,limit 默认其实位置为0,也就是从第一条记录开始,limit中默认位置的表述就和编程语言中描述列表元素下标一样-----从0开始。

示例如下

select * from employee order by salary desc  limit 3; -- 默认初始位置为0 

select * from employee order by salary desc limit 0,5;--从第0开始,即先查询出第一条,然后包含这一条在内往后查5条

select * from employee order by salary desc limit 5,5; -- 从第5开始,即先查询出第6条,然后包含这一条在内往后查5条

小试牛刀

#查看薪资最高的,先排序,再限制
select * from employee order by salary desc limit 1;
#另一种 方式
select * from employee where salary = (select max(salary) from employee); 
#从0开始,向后取5个(依次类推)
select * from employee limit 0,5;
select * from employee limit 5,5;
select * from employee limit 10,5;
select * from employee limit 15,5;


8.语法总结

目前,各个语法的功能都清楚了,接下来就把所有的语句总结一下
PS:没有写相应的语法术语就使用相关默认值

流程图代码


graph TB 
a[select--当做入口]-.语法顺序1.->b[distinct 去重]
b-.语法顺序2.->c[from 库.表inner/left/right join 库.表 on 关联条件] 
c-.语法顺序3.->d[where 条件]
d-.语法顺序4.->e[group by 分组条件-默认整体为一组]
e-.语法顺序5.->f[having 过滤] 
f-.语法顺序6.->g[order by 排序字段]
g-.语法顺序7.->h[limit n 限制显示的条数]

a-->|执行1|c
c-->|执行2|d
d-->|执行3|e
e-->|执行4|f
f-->|执行5|b
b-->|执行6|g
g-->|执行7|h

流程图

上面的图可以如下解释

select  (将其看成是调用查询的总入口)
    distinct[去重] 字段1,字段2,字段3----执行优先级5 去重
    from 库.表    --------------------执行优先级1  最高
    where 条件    --------------------执行优先级2 不能用聚合函数
    group by 分组条件(默认整体为一组)----执行优先级3 在此之后能用聚合函数
    having 过滤    -------------------执行优先级4 能用聚合函数
    order by 排序字段 -----------------执行优先级6 
    limit n; 限制显示的条数-------------执行优先级7 


9.正则查询

正则表达式;和python的re模块的如出一辙,有小部分使用可能有点区别

示例

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 employee where name like 'jin%';
select * from employee where name regexp '^jin';
select * from employee where name regexp '^jin.*(g|n)$';

posted @ 2018-04-24 11:08  哈哈大圣  阅读(147)  评论(0编辑  收藏  举报