Mysql 单表查询-排序-分页-group by初识
Mysql 单表查询-排序-分页-group by初识
对于select 来说, 分组聚合(((group by; aggregation), 排序 (order by** ), 分页查询 (limit), 等这些操作, 都是结合 where 过滤(算术表达式, 逻辑表达式, 判空, 范围过滤, 模糊查询), 来进一步对数据集为所欲为地操作哦, group by 也是我工作中每天都必用的, 因为我每天要拆分数据嘛, 先按一或多个字段 group by, 然后, 再对每组的抑或多个字段进行聚合(sum, avg, max, quartile...)等.
直接来理解SQL分组聚合, 一开始还是不容易的, 一个是对group by 不熟, 另一个对sql语句不熟. 针对这点, 我是每天都在用Excel的透视表, 各种透视, 多条件透视, 整吐了过后, 就彻底明白了. 虽然我是有些讨厌Excel, 但不得不说, 它能让你直观地理解很多数据, 数据结构, 编程相关的概念.
数据依然是上篇, students表(where 初识那一篇).
准备测试数据
-- win 下, 进入终端 (cmd + R)
mysql -u root -p
C:\Users\chenjie>mysql -u root -p
Enter password: ********
-- 再重新来手打一遍吧, 一点经验之谈, 对我学习方法就是, 多抄代码, 抄多了, 手就有感觉了, 跟打字一样的, 变成了一种下意识, 而非脑袋过一遍就觉得懂了哦,真的是唯手熟尔哦.
-- 创建数据库
drop database if exists student_db;
create database student_db charset=utf8;
use student_db;
-- 创建学生表-测试
create table students(
id int unsigned primary key auto_increment not null,
name varchar(20) default "",
age tinyint unsigned default 0, -- 建议给默认值, Null查询慢
height decimal(5,2), -- 共5位, 小数占2位
gender enum("男", "女", "未填写"),
class_id int unsigned default 1,
is_delete bit default 0
);
-- 班级表
drop table if exists classes;
create table classes(
id int unsigned auto_increment primary key not null,
name varchar(20) not null
);
-- 插入偶像, 用于测试哦只是, 别无它意
insert into students values
(0,'爱因斯坦',18,180.00,1,1,0),
(0,'居里夫人',18,180.00,2,2,1),
(0,'小王子',14,185.00,1,1,0),
(0,'李银河',59,175.00,1,2,1),
(0,'黄蓉',38,160.00,2,1,0),
(0,'冰心',28,150.00,2,2,1),
(0,'王祖贤',18,172.00,2,1,1),
(0,'周杰伦',36,NULL,1,1,0),
(0,'王小波',57,181.00,1,2,0),
(0,'林徽因',25,166.00,2,2,0),
(0,'小星',33,162.00,3,3,1),
(0,'张爱玲',12,180.00,2,4,0),
(0,'冯唐',12,170.00,1,4,0),
(0,'胡适',34,176.00,2,5,0);
insert into classes values
(0, "科学"),
(0, "艺术");
-- 如果失败, 要么就是语法不对, 要么就是 没有开服服务
Query OK, 14 rows affected (0.03 sec)
Records: 14 Duplicates: 0 Warnings: 0
mysql>
mysql> insert into classes values
-> (0, "科学"),
-> (0, "艺术");
Query OK, 2 rows affected (0.04 sec)
Records: 2 Duplicates: 0 Warnings: 0
-- 测试
select * from students;
select * from calsses;
+----+--------------+------+--------+-----------+----------+-----------+
| id | name | age | height | gender | class_id | is_delete |
+----+--------------+------+--------+-----------+----------+-----------+
| 1 | 爱因斯坦 | 18 | 180.00 | 男 | 1 | |
| 2 | 居里夫人 | 18 | 180.00 | 女 | 2 | |
| 3 | 小王子 | 14 | 185.00 | 男 | 1 | |
| 4 | 李银河 | 59 | 175.00 | 男 | 2 | |
| 5 | 黄蓉 | 38 | 160.00 | 女 | 1 | |
| 6 | 冰心 | 28 | 150.00 | 女 | 2 | |
| 7 | 王祖贤 | 18 | 172.00 | 女 | 1 | |
| 8 | 周杰伦 | 36 | NULL | 男 | 1 | |
| 9 | 王小波 | 57 | 181.00 | 男 | 2 | |
| 10 | 林徽因 | 25 | 166.00 | 女 | 2 | |
| 11 | 小星 | 33 | 162.00 | 未填写 | 3 | |
| 12 | 张爱玲 | 12 | 180.00 | 女 | 4 | |
| 13 | 冯唐 | 12 | 170.00 | 男 | 4 | |
| 14 | 胡适 | 34 | 176.00 | 女 | 5 | |
+----+--------------+------+--------+-----------+----------+-----------+
14 rows in set (0.00 sec)
mysql> select * from classes;
+----+--------+
| id | name |
+----+--------+
| 1 | 科学 |
| 2 | 艺术 |
+----+--------+
-- 手抖了, 改下 胡适先生的性别
update students as s
set s.gender := "男"
where s.name = "胡适";
Query OK, 1 row affected (0.10 sec)
Rows matched: 1 Changed: 1 Warnings: 0
-- 检测一波
select s.name, s.gender
from students s -- 养成 as 取别名的习惯, 为后面多张表连接预热哦
where s.name = "胡适";
+--------+--------+
| name | gender |
+--------+--------+
| 胡适 | 男 |
+--------+--------+
1 row in set (0.00 sec)
排序 order by
- order by 字段
- desc 降序
- asc 升序, 默认是asc
-- 查询18到28之间的女生姓名及身高, 并按年龄降序
select s.name, s.height
from students as s
where (age between 18 and 24) and (gender = "女")
order by age desc;
+--------------+--------+
| name | height |
+--------------+--------+
| 居里夫人 | 180.00 |
| 王祖贤 | 172.00 |
+--------------+--------+
2 rows in set (0.00 sec)
-- 查询年龄在18到35岁的男性姓名, 年龄,身高, 班级, 要求按身高降序, 身高相同则按年龄升序
select s.name, s.age, s.height, s.class_id
from students as s
where (age between 18 and 35) and (gender = "男")
order by height desc, age asc;
+--------------+------+--------+----------+
| name | age | height | class_id |
+--------------+------+--------+----------+
| 爱因斯坦 | 18 | 180.00 | 1 |
| 胡适 | 34 | 176.00 | 5 |
+--------------+------+--------+----------+
-- 查询18-28的女生, 要求按身高降序, 若身高相同则按年龄升序, 身高相同则按id降序
select *
from students s -- as 可以省略的
where age between 18 and 28 and gender = "女"
order by height desc, age asc, id desc;
+----+----------+-----+--------+--------+----------+-----------+
| id | name | age | height | gender | class_id | is_delete |
+----+----------+-----+--------+--------+----------+-----------+
| 2 | 居里夫人 | 18 | 180.00 | 女 | 2 | 1 |
| 7 | 王祖贤 | 18 | 172.00 | 女 | 1 | 1 |
| 10 | 林徽因 | 25 | 166.00 | 女 | 2 | 0 |
| 6 | 冰心 | 28 | 150.00 | 女 | 2 | 1 |
+----+----------+-----+--------+--------+----------+-----------+
4 rows in set (0.06 sec)
分页查询 limit
为啥要分页查询呢, 就好比我们平时浏览网页时, 一下也看不完那么多内容的, 网页内容也是随用户看一点, 加载一点, 这样, 边看边查询, 就不会给服务器太大压力了呀.
-- 语法: limit start=0, count;
-- 需求: 每页显示 m 条数据, 当前显示第 n 页;
-- 原理: 第 n 页前有(n-1)页数据, 即(n-1)*m 条数据, 即第n页的的小标 start = (n-1)*m;
-- 案例: 假设有10条数据, 要求每页显示2条数据, 要显示第3页数则, start=(3-1)*2=4, 即 limit 4;
-- 查询前3个数据
select * from students limit 3
-- 查询第3个页面, 每页显示2个数据
-- start = (3-1)* = 4
select * from students limit 4, 2;
+----+------+-----+--------+--------+----------+-----------+
| id | name | age | height | gender | class_id | is_delete |
+----+------+-----+--------+--------+----------+-----------+
| 5 | 黄蓉 | 38 | 160.00 | 女 | 1 | 0 |
| 6 | 冰心 | 28 | 150.00 | 女 | 2 | 1 |
+----+------+-----+--------+--------+----------+-----------+
-- 查询第4页, 每页显示3个学生的姓名, 班级
-- start = (4-1)*3 = 9
select s.name, s.class_id
from students s
limit 9, 3;
+--------+----------+
| name | class_id |
+--------+----------+
| 林徽因 | 2 |
| 小星 | 3 |
| 张爱玲 | 4 |
+--------+----------+
3 rows in set (0.08 sec)
分组 group by
分组聚合是数据分析的基础, 就我平时的工作而言, 天天都是在分组聚合, 俗称"拉一下数据, 透视一下表, 拆分数更细",都是一个道理, 先分组, 再聚合.
以Excel表为例, 说明一下字段的值. 基本就两种, 类别值字段 和 连续值字段, 比如年龄就是一个连续值字段, 可以对其求平均值, 最大值等(当然也可以离散化). 而对于性别来讲, 就是分类值字段, 要么男性, 要么女性, 要么...反正数得过来, 一般很少听到, 对性别求平均, 求最值, 大概率是没有滴吧.
常见聚合函数
max, min, sqrt, sum, avg, count ...等
-- 最高的身高是多少
select max(height) from students;
+-------------+
| max(height) |
+-------------+
| 185.00 |
+-------------+
-- 身高最高的女生姓名,身高, 年龄 (提前剧透一下子查询吧)
-- step1: 先查询最高的女性身高, 得到一个标量值
select max(s.height)
from students as s
where gender="女";
+---------------+
| max(s.height) |
+---------------+
| 180.00 |
+---------------+
-- step2: 将该值作为where条件即可
select s.name, s.age, s.height
from students as s
where height = (
select max(s.height)
from students as s
where gender="女"
);
+----------+-----+--------+
| name | age | height |
+----------+-----+--------+
| 爱因斯坦 | 18 | 180.00 |
| 居里夫人 | 18 | 180.00 |
| 张爱玲 | 12 | 180.00 |
+----------+-----+--------+
-- 所有学生的平均年龄, 当然可直接用avg函数
-- count(*)表示不忽略空值计算
select sum(age) / count(id) as "平均年龄"
from students;
+----------+
| 平均年龄 |
+----------+
| 28.7143 |
+----------+
1 row in set (0.07 sec)
-- 计算女性的平均身高, 并保留2位小数
select round(avg(s.height), 2) as "女生平均身高"
from students as s
where s.gender="女";
+--------------+
| 女生平均身高 |
+--------------+
| 168.00 |
+--------------+
1 row in set (0.06 sec)
分组groupby
分组就一种情景, 按单字段或多字段 分组, 不懂的请自行熟练Excel透视表 就明白了.
-- 根据性别分组, 显示所有的年龄
select s.gender
from students as s
group by gender;
+--------+
| gender |
+--------+
| 男 |
| 女 |
| 未填写 |
+--------+
3 rows in set (0.06 sec)
-- 计算不同班级的人数各为多少
select s.class_id, count(id) as "班级人数"
from students as s
group by class_id;
+----------+----------+
| class_id | 班级人数 |
+----------+----------+
| 1 | 5 |
| 2 | 5 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
+----------+----------+
5 rows in set (0.06 sec)
-- 计算每个班学生的平均年龄, 结果保留2位小数
select s.class_id as "班级编号", round(avg(age),2) as "平均年龄"
from students s
group by s.class_id;
+----------+----------+
| 班级编号 | 平均年龄 |
+----------+----------+
| 1 | 24.80 |
| 2 | 37.40 |
| 3 | 33.00 |
| 4 | 12.00 |
| 5 | 34.00 |
+----------+----------+
5 rows in set (0.07 sec)
-- 查询出每个班级中的每个学生的姓名
-- group_concat() 组内查询
select s.class_id, group_concat(s.name)
from students as s
group by class_id;
+----------+------------------------------------+
| class_id | group_concat(s.name) |
+----------+------------------------------------+
| 1 | 爱因斯坦,小王子,黄蓉,王祖贤,周杰伦 |
| 2 | 居里夫人,李银河,冰心,王小波,林徽因 |
| 3 | 小星 |
| 4 | 张爱玲,冯唐 |
| 5 | 胡适 |
+----------+------------------------------------+
5 rows in set (0.08 sec)
-- 查询平均年龄大于25岁的学生姓名, 性别
-- 方案1: 以性别分组, 然后 having 组内过滤
-- 方案2: 子查询
select gender, group_concat(name), avg(age)
from students as s
group by gender
having avg(age) >=25;
+--------+------------------------------------------------+----------+
| gender | group_concat(name) | avg(age) |
+--------+------------------------------------------------+----------+
| 男 | 爱因斯坦,小王子,李银河,周杰伦,王小波,冯唐,胡适 | 32.8571 |
| 未填写 | 小星 | 33.0000 |
+--------+------------------------------------------------+----------+
2 rows in set (0.07 sec)
-- 查询不同性别中, 人数多于2个的学生性别,身高
select gender, group_concat(name), count(id)
from students
group by gender
having count(id) > 2;
+--------+------------------------------------------------+-----------+
| gender | group_concat(name) | count(id) |
+--------+------------------------------------------------+-----------+
| 男 | 爱因斯坦,小王子,李银河,周杰伦,王小波,冯唐,胡适 | 7 |
| 女 | 居里夫人,黄蓉,冰心,王祖贤,林徽因,张爱玲 | 6 |
+--------+------------------------------------------------+-----------+
2 rows in set (0.08 sec)
-- with rollup 汇总, 不习惯sql汇总, 用其他编程语言来整更灵活方便呀
select gender,group_concat(name)
from students
group by gender
with rollup;
小结
where 过滤, 结合排序, 分组, 聚合 这一套组合操作, 能满足更多的业务场景
排序: order by 默认升序asc; 降序desc
分页: limit; 语法: limit start=0, count; 查询第n页显示m个数据, 则 start = (n-1) * m
分类汇总, 先分类, 再汇总, 特别特重要, group by 结合聚合函数, Excel的数据透视表玩6了就没问题.
常见聚合函数: min, max, sum, avg, count, round, sqrt .....
group by 及理解组内过滤 group_concat 的内在逻辑.
预告: 下一节整一波多表连接 Join查询结合group by 和 aggregate.
Mysql 单表查询-排序-分页-group by初识的更多相关文章
- python 3 mysql 单表查询
python 3 mysql 单表查询 1.准备表 company.employee 员工id id int 姓名 emp_name varchar 性别 sex enum 年龄 age int 入职 ...
- Mysql 单表查询where初识
Mysql 单表查询where初识 准备数据 -- 创建测试库 -- drop database if exists student_db; create database student_db ch ...
- Mysql 单表查询 子查询 关联查询
数据准备: ## 学院表create table department( d_id int primary key auto_increment, d_name varchar(20) not nul ...
- MySQL单表查询(分组-筛选-过滤-去重-排序)
目录 一:单表查询 1.单表查询(前期准备) 2.插入记录(写入数据) 3.查询关键字 二:查询关键字之where 1.查询id大于等于3小于等于6的数据 2.查询薪资是20000或者18000或者1 ...
- MySQL单表查询
MySQL之单表查询 创建表 # 创建表 mysql> create table company.employee5( id int primary key AUTO_INCREMENT not ...
- mysql 单表查询
一 单表查询的语法 SELECT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条数 二 ...
- SQL学习笔记四(补充-1)之MySQL单表查询
阅读目录 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER BY 八 限制查询的记录 ...
- python开发mysql:单表查询&多表查询
一 单表查询,以下是表内容 一 having 过滤 1.1 having和where select * from emp where id > 15; 解析过程;from > where ...
- 0x06 MySQL 单表查询
一 单表查询语法 SELECT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条数 二 关键字 ...
随机推荐
- ESA2GJK1DH1K基础篇: 阿里云物联网平台: 测试云平台显示MQTT客户端发过来的消息
现在这里空空如也 咱自定义的也没有数据 现在就是传上来温度数据,让这里显示温度数据 你发布的主题 /sys/a1m7er1nJbQ/Mqtt/thing/event/property/post 发布 ...
- document.write和innerHTML的区别?
document.write是直接重写整个页面,innerHTML针对所属DOM节点进行重写,效率优于document.write.
- ISE 14.7安装教程最新版(Win10安装)
一.下载 第一步下载首先自己下载好四个压缩包,把第一个解压,其余的三个不用解压,然后去第一个解压后的文件夹打开启动程序. 第二步是点击启动程序后会有以下界面 next到下一个界面,这个时候需要把之前没 ...
- postgresql小计
1. postgresql执行结束后,判断结果是否成功,有几种结果 typedef enum { PGRES_EMPTY_QUERY = 0, /* empty query string was ex ...
- Spring Security教程(五)
在之前的几篇security教程中,资源和所对应的权限都是在xml中进行配置的,也就在http标签中配置intercept-url,试想要是配置的对象不多,那还好,但是平常实际开发中都往往是非常多的资 ...
- Centos查看虚拟机IP地址及使用XShell连接
1.在VMware中安装Centos7系统[1] 2.查看虚拟机里的Centos7的IP[2] 1)查看IP 输入ip查询命名 ip addr 发现 ens33 没有 inet 这个属性,那么就没法通 ...
- 【2019年05月13日】A股ROE最高排名
个股滚动ROE = 最近4个季度的归母净利润 / ((期初归母净资产 + 期末归母净资产) / 2). 查看更多个股ROE最高排名. 兰州民百(SH600738) - 滚动ROE:86.45% - 滚 ...
- [原创]K8域控植入脚本生成器(内网渗透/RPC不可用解决方案)
0x001 简介 当IPC或WMI无法访问域内机器时,可通过脚本上控. 我们可以在个人机的开机注销重启脚本里配置持久化. 域环境下同样也有开机脚本,但得在在域控机器配置 可以使用BAT\VBS等脚本, ...
- reduce深入理解
// map console.log([1, 2, 3, 4, 5].reduce((a, v) => { a.push(v * v); return a },[])); //filter co ...
- react加入websocket
1.首先创建一个公共的组件,封装websocket 代码如下 /** * 参数:[socketOpen|socketClose|socketMessage|socketError] = func,[s ...