数据库(七):单表查询
进击のpython
数据库——单表查询
数据库在使用的时候,更多的是查看数据,而学会了外键之后,查询就已经不仅仅是针对单个表的操作了
同时,对于单表的查询要求也是越来越高,而基于此,原先的简单查询就有点心有余而力不足了
所以说,接下来就是进阶的查询!首先要确定一点的就是,查询是针对记录的,这点要明确哦
单表查询
既然是进阶,就一定有不一样的花板子~完整的单表查询指令如下:
select distinct字段名1,字段名2 from 库.表
where 条件
group by 分组
having 过滤
order by 排序
limit 限制
;
简单查询
distinct:去重
mysql> select post from employee;
+-----------------------------------------+
| post |
+-----------------------------------------+
| 驻沙河办事处外交大使 |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| sale |
| sale |
| sale |
| sale |
| sale |
| operation |
| operation |
| operation |
| operation |
| operation |
+-----------------------------------------+
18 rows in set (0.00 sec)
mysql> select distinct post from employee;
+-----------------------------------------+
| post |
+-----------------------------------------+
| 驻沙河办事处外交大使 |
| teacher |
| sale |
| operation |
+-----------------------------------------+
4 rows in set (0.32 sec)
同时查询的时候是支持四则运算的:
mysql> select name,salary*12 from employee;
+------------+-------------+
| name | salary*12 |
+------------+-------------+
| egon | 87603.96 |
| alex | 12000003.72 |
| wupeiqi | 99600.00 |
| yuanhao | 42000.00 |
| liwenzhou | 25200.00 |
| jingliyang | 108000.00 |
| jinxin | 360000.00 |
| 成龙 | 120000.00 |
| 歪歪 | 36001.56 |
| 丫丫 | 24004.20 |
| 丁丁 | 12004.44 |
| 星星 | 36003.48 |
| 格格 | 48003.96 |
| 张野 | 120001.56 |
| 程咬金 | 240000.00 |
| 程咬银 | 228000.00 |
| 程咬铜 | 216000.00 |
| 程咬铁 | 204000.00 |
+------------+-------------+
18 rows in set (0.00 sec)
mysql> select name,salary*12 as annual_salary from employee;
+------------+---------------+
| name | annual_salary |
+------------+---------------+
| egon | 87603.96 |
| alex | 12000003.72 |
| wupeiqi | 99600.00 |
| yuanhao | 42000.00 |
| liwenzhou | 25200.00 |
| jingliyang | 108000.00 |
| jinxin | 360000.00 |
| 成龙 | 120000.00 |
| 歪歪 | 36001.56 |
| 丫丫 | 24004.20 |
| 丁丁 | 12004.44 |
| 星星 | 36003.48 |
| 格格 | 48003.96 |
| 张野 | 120001.56 |
| 程咬金 | 240000.00 |
| 程咬银 | 228000.00 |
| 程咬铜 | 216000.00 |
| 程咬铁 | 204000.00 |
+------------+---------------+
18 rows in set (0.37 sec)
看到为什么写两个了吧,看到区别了吧~
还有就是字符串拼接,怎么拼接呢?
select concat('name:',name) from employee;
mysql> select concat('name:',name) from employee;
+------------------------+
| concat('name:',name) |
+------------------------+
| name:egon |
| name:alex |
| name:wupeiqi |
| name:yuanhao |
| name:liwenzhou |
| name:jingliyang |
| name:jinxin |
| name:成龙 |
| name:歪歪 |
| name:丫丫 |
| name:丁丁 |
| name:星星 |
| name:格格 |
| name:张野 |
| name:程咬金 |
| name:程咬银 |
| name:程咬铜 |
| name:程咬铁 |
+------------------------+
18 rows in set (0.00 sec)
where约束
where字句中可以使用:
- 比较运算符:> < >= <= <> !=
- between 80 and 100 值在80到100之间
- in(80,90,100) 值是10或20或30
- like 'ponny%'
pattern可以是%或_,
%表示任意多字符
_表示一个字符 - 逻辑运算符:在多个条件直接可以使用逻辑运算符 and or not
这个一部分讲的在前面都有涉及,所以,就不举例了,你自己尝试使用
group by
这是分组,分组就是把有相同或相似特征的放在一起
比如说把男的都放在一起,把女的都放在一起
而且group by 只能够查询该分组的组名,查不到别的东西
mysql> select * from employee 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 |
| 1 | egon | male | 18 | 2017-03-01 | 驻沙河办事处外交大使 | NULL | 7300.33 | 401 | 1 |
+----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
4 rows in set (0.41 sec)
你这不骗我吗?哪只有分组数据啊,这么多数据呢!
但是你会发现打印出来的都是每组的第一条数据,这是没有意义的
别慌,其实这是mysql的设定,我们需要把模式改成严格模式才可以
set global sql_mode='ONLY_FULL_GROUP_BY';
怎么设置完还这样呢?还记得设置自增时候的步长和起始偏移量的时候吗?我们需要关掉重开一下!
mysql> select * from employee group by post;
ERROR 1055 (42000): 't.employee.id' isn't in GROUP BY
但是其实也没有用,因为分组的目的不是想看看同类的,而是想对这些人做一个数据处理
比如像想统计人数啊之类的~~那就用到了聚合函数了!
那题道具和函数,就得好好说或聚合函数,聚合函数一共有这些:
max min avg sum count
比如说我们统计一下每个职位的人数~
select count(id) from employee group by post
mysql> select post,count(name) from employee group by post;
+-----------------------------------------+-------------+
| post | count(name) |
+-----------------------------------------+-------------+
| operation | 5 |
| sale | 5 |
| teacher | 7 |
| 驻沙河办事处外交大使 | 1 |
+-----------------------------------------+-------------+
4 rows in set (0.00 sec)
要是想打印人数大于五的部门信息那我应该是这么写:
select concat('职位:',post,' 人数:',count(name),
' 姓名:',group_concat(name)) as info,
count(name)>5 from employee group by post;
尤其是看到group_concat(name)的用法!!!
你可能执行的结果是这个:
+--------------------------------------------------------------------------------------------+--------+
| info | 数量 |
+--------------------------------------------------------------------------------------------+--------+
| 职位:operation人数:5姓名:程咬铁,程咬铜,程咬银,程咬金,张野 | 0 |
| 职位:sale人数:5姓名:格格,星星,丁丁,丫丫,歪歪 | 0 |
| 职位:teacher人数:7姓名:成龙,jinxin,jingliyang,liwenzhou,yuanhao,wupeiqi,alex | 1 |
| 职位:驻沙河办事处外交大使人数:1姓名:egon | 0 |
+--------------------------------------------------------------------------------------------+--------+
这跟本来想的不一样啊!别急~~~你还差一个知识点!先放在这
那我们可以逆向思维,如果不分组,是不是,就所有数据都是一组了!
那是不是也可以用聚合函数!
那我比如说想查找最高工资,是不是就会了!
having
这就是差的知识点!having 过滤
诶???我好像记得之前也有个过滤,好像是where,那他们有什么区别吗?
#!!!执行优先级从高到低:where > group by > having
#1. Where 发生在分组group by之前,因而Where中可以有任意字段,但是绝对不能使用聚合函数。
#2. Having发生在分组group by之后,因而Having中可以使用分组的字段,无法直接取到其他字段,可以使用聚合函数
(验证自己验证ok?)
那饿哦们就可以接着把上面的代码优化为:
select concat('职位:',post,'人数:',count(name),'姓名:',group_concat(name)) info from employee group by post having count(id)>5;
这回再打印,是不是就是预料之中的结果了!
order by
排序
表格默认的是id排序,那我想根据年龄排序,怎么办呢?
select * from employee order by age;
可以看到是默认升序,那要是想要倒序呢?
select * from employee order by age desc
那你可能发现age有相等的时候,那我要是想相等的时候按照id排序怎么做呢?
select * from employee order by age,id
limit 限制
这个就是限制显示条数,限制显示前三条:
mysql> select * from employee limit 3;
+----+---------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+---------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| 1 | egon | male | 18 | 2017-03-01 | 沙河办事处外交大使 | NULL | 7300.33 | 401 | 1 |
| 2 | alex | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
| 3 | wupeiqi | male | 81 | 2013-03-05 | teacher | NULL | 8300.00 | 401 | 1 |
+----+---------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
3 rows in set (0.09 sec)
当然它其实还有分页的功能:
select * from employee limit 0,5;
代表着从0开始往后取5个
(表结构看不清就看id)
select * from employee limit 0,5;
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| 1 | egon | male | 18 | 2017-03-01 | 驻沙河办事处外交大使 | NULL | 7300.33 | 401 | 1 |
| 2 | alex | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
| 3 | wupeiqi | male | 81 | 2013-03-05 | teacher | NULL | 8300.00 | 401 | 1 |
| 4 | yuanhao | male | 73 | 2014-07-01 | teacher | NULL | 3500.00 | 401 | 1 |
| 5 | liwenzhou | male | 28 | 2012-11-01 | teacher | NULL | 2100.00 | 401 | 1 |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
5 rows in set (0.00 sec)
从5开始往后取五个:
mysql> select * from employee limit 5,5;
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
| 6 | jingliyang | female | 18 | 2011-02-11 | teacher | NULL | 9000.00 | 401 | 1 |
| 7 | jinxin | male | 18 | 1900-03-01 | teacher | NULL | 30000.00 | 401 | 1 |
| 8 | 成龙 | male | 48 | 2010-11-11 | teacher | NULL | 10000.00 | 401 | 1 |
| 9 | 歪歪 | female | 48 | 2015-03-11 | sale | NULL | 3000.13 | 402 | 2 |
| 10 | 丫丫 | female | 38 | 2010-11-01 | sale | NULL | 2000.35 | 402 | 2 |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
5 rows in set (0.00 sec)
接下来的分页就不演示了~
那在这我就要提一下书写顺序和执行顺序了,毕竟约束条件这么多,总要有个优先级嘛:
正则表达式
where 后面虽然不能使用聚合函数,但是是可以使用正则匹配的
selece * from employee where name regexp '^ale';
以ale开头的
其实他跟select * from employee where name like 'ale%';
是一样的
select * from employee where name regexp 'on$';
以on结尾的
select * from employee where name regexp 'm{2}';
里面有mm的
以上的方法都自己去试一下
那我要是想以什么开头,以什么结尾呢?
select * from employee where name regexp '^jin.*(g|n)$';
这就是以 jin 开头,以g或者n结尾的name字段的数据
那至此,所有的约束就全结束了!
接下来就是多表查询了~