1. group by的常规用法

group by的常规用法是配合聚合函数,利用分组信息进行统计,常见的是配合max等聚合函数筛选数据后分析,以及配合having进行筛选后过滤。

  • 假设现有数据库表如下:
    表user_info,id主键,user_id唯一键
CREATE TABLE `user_info` (
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`user_id` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '用户编号',
`grade` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '年级',
`class` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '班级',
PRIMARY KEY (`id`),
UNIQUE INDEX `uniq_user_id` (`user_id`)
)
ENGINE=InnoDB
  • 数据
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (10, '', 'C', 'B');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (9, '', 'C', 'a');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (8, '', 'B', 'b');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (7, '', 'B', 'b');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (6, '', 'B', 'a');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (5, '', 'B', 'a');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (4, '', 'A', 'b');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (3, '', 'A', 'b');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (2, '', 'A', 'a');
INSERT INTO `user_info` (`id`, `user_id`, `grade`, `class`) VALUES (1, '', 'A', 'a');

id user_id grade class
1 10221 A a
2 10222 A a
3 10223 A b
4 10224 A b
5 10225 B a
6 10226 B a
7 10227 B b
8 10228 B b
9 10229 C a
10 10230 C b
  • 聚合函数max
select max(user_id),grade from user_info group by grade ;

结果

max(user_id) grade
10224 A
10228 B
10230 C

这条sql的含义很明确,将数据按照grade字段分组,查询每组最大的user_id以及当前组内容。注意,这里分组条件是grade,查询的非聚合条件也是grade。这里不产生冲突。

  • having
select max(user_id),grade from user_info group by grade  having grade>'A'

结果

max(user_id) grade
10228 B
10230 C

这条sql与上面例子中的基本相同,不过后面跟了having过滤条件。将grade不满足’>A’的过滤掉了。注意,这里分组条件是grade,查询的非聚合条件也是grade。这里不产生冲突。

2. group by的非常规用法

select max(user_id),id,grade from user_info group by grade  

结果

max(user_id) id grade
10224 1 A
10228 5 B
10230 9 C

这条sql的结果就值得讨论了,与上述例子不同的是,查询条件多了id一列。数据按照grade分组后,grade一列是相同的,max(user_id)按照数据进行计算也是唯一的,id一列是如何取值的?看上述的数据结果,
推论:id是物理内存的第一个匹配项。
究竟是与不是需要继续探讨。

修改数据

  • 修改id按照上述数据结果,将id=1,改为id=99,执行sql后结论:
max(user_id) id grade
10224 2 A
10228 5 B
10230 9 C

显然,与上述例子的结果不同。第一条数据id变成了99,查出的结果第一条数据的id从1变成了2。表明,id这个非聚合条件字段的取值与数据写入的时间无关,因为id=1的记录是先于id=2存在的,修改的数据不过是修改了这条数据的内容。结合mysql的数据存储理论,由于id是主键,所以数据在检索是是按照主键排序后进行过滤的,因此
推论:id字段的选取是按照mysql存储的检索数据匹配的第一条
将id改为1后恢复了原始结果,无法推翻上述推论。

  • 更改查询条件

    select max(user_id),user_id,id,grade from user_info group by grade
max(user_id) user_id id grade
10224 10221 1 A
10228 10225 5 B
10230 10229 9 C

将数据user_id改为10999后,执行结果为

max(user_id) user_id id grade
10224 10999 1 A
10228 10225 5 B
10230 10229 9 C

修改了user_id后,并没有改变查询到的数据条目,因此得出修改唯一键并不能影响查询匹配的条目规则,所以条目规则依然是匹配第一条,即id=1。

结论

  • 当group by 与聚合函数配合使用时,功能为分组后计算
  • 当group by 与having配合使用时,功能为分组后过滤
  • 当group by 与聚合函数,同时非聚合字段同时使用时,非聚合字段的取值是第一个匹配到的字段内容,即id小的条目对应的字段内容。

mysql中group by 的用法解析的更多相关文章

  1. mysql中INSTR函数的用法

    mysql中INSTR函数的用法 INSTR(字段名, 字符串) 这个函数返回字符串在某一个字段的内容中的位置, 没有找到字符串返回0,否则返回位置(从1开始) SELECT * FROM tblTo ...

  2. 带你了解数据库中group by的用法

    前言 本章主要介绍数据库中group by的用法,也是我们在使用数据库时非常基础的一个知识点.并且也会涉及Join的使用,关于Join的用法,可以看我写的上一篇文章:带你了解数据库中JOIN的用法如有 ...

  3. 转:深入研究mysql中group by与order by取分类最新时间内容

    鉴于项目的需要,就从网上找到该文章,文章分析得很详细也很易懂,在android里, (不知道是不是现在水平的限制,总之我还没找到在用ContentProvider时可以使用子查询),主要方法是用SQL ...

  4. MySQL中INSERT的一般用法

    原文链接:http://www.blogjava.net/midnightPigMan/archive/2014/12/15/421406.html MySQL中INSERT的一般用法 INSERT语 ...

  5. mysql 中find_in_set()和in()用法比较

    mysql 中find_in_set()和in()用法比较 在mysql中in可以包括指定的数字,而find_in_set()用于特定的数据类型. find_in_set 函数使用方法 个例子来说:有 ...

  6. 深入研究mysql中group by与order by取分类最新时间内容

    鉴于项目的需要,就从网上找到该文章,文章分析得很详细也很易懂,在android里,(不知道是不是现在水平的限制,总之我还没找到在用 ContentProvider时可以使用子查询),主要方法是用SQL ...

  7. oracle 中GROUP BY的用法

    转自:http://blog.csdn.net/basenet855x/article/details/6694150 问题: select item.itemnum,item.in1,item.in ...

  8. MYSQL 中GROUP BY

    group by 用法解析 group by语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表. SELECT子句中的列名必须为分组列或列函数.列函数对于GROUP BY子 ...

  9. MYSQL中replace into的用法以及与inset into的区别

    在向表中插入数据时,我们经常会遇到这样的情况:1.首先判断数据是否存在:2.如果不存在,则插入:3.如果存在,则更新. 在SQL Server中可以这样处理: if not exists (selec ...

随机推荐

  1. 【css】圆角 +文本阴影

    1.  css3 圆角 http://www.cnblogs.com/lhb25/archive/2013/01/30/css3-border-radius.html 2. text shawdow ...

  2. 简单聊聊不可或缺的Nginx反向代理服务器--实现负载均衡【上篇】

    今天又是新的一周,我养足了精神去对待新一周的工作,但是今天到公司发现还是有一点空闲时间的,所以就想与之前接触过的Nginx再交往得更深一点儿. 什么是Nginx: Nginx是一款高性能的http服务 ...

  3. jquery左右轮播

    <!--------html代码:-----------> <!DOCTYPE html><html><head><title>carous ...

  4. angular学习(一)-- Expression

    1.1 表达式:Expression 在AngularJS中,表达式是一种类似于模板引擎的语法, 可以在书写的位置 "输出" 数据. 基本使用 表达式写在双大括号内:{{ expr ...

  5. 在基于TypeScript的LayaAir HTML5游戏开发中使用AMD

    在基于TypeScript的LayaAir HTML5游戏开发中使用AMD AMD AMD是"Asynchronous Module Definition"的缩写,意思就是&quo ...

  6. vTPM环境部署(ubuntu)

    注:1.系统:ubuntu16.04LTS2.ISO镜像:/home/huanghaoxiang/ubuntu-server.iso3.IMG路径:/home/TPM-Machine4.Login: ...

  7. 关于DB2版本、补丁升级和回退的总结[转载]

    首先介绍几个概念 RELEASE的升级就是版本升级,例如9.1→9.5→9.7→10.1,可以跳版本升级,例如9.1→10.1 FIX PACK简称FP,就是打补丁,例如9.7.1→9.7.2,每个版 ...

  8. QtWebEngine加载资料缓慢

    最近由于项目需要(另外Qt后续版本也将不再支持QtWebKit),把Qt工程涉及QtWebKit的移植为QtWebEngine,用的Qt版本为5.5.0,结果出现QWebEngineView加载网页是 ...

  9. .Net之用户控件笔记

    前端初始化: 记录点:不需要写jquery的onload,只需要在<script></script>里面直接调用 <script type="text/java ...

  10. PACS发展历史

    最先推动 PACS发展的动力来自于传统的相机厂家.这是因为当数字化浪潮到来的时候,他们首先就意识到这对他们的产品是一个不可逆转的巨大的冲击.他们当然有着自己的优势:对各个厂家的设备连接能力有着最为清楚 ...