mysql中group by 的用法解析
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 的用法解析的更多相关文章
- mysql中INSTR函数的用法
mysql中INSTR函数的用法 INSTR(字段名, 字符串) 这个函数返回字符串在某一个字段的内容中的位置, 没有找到字符串返回0,否则返回位置(从1开始) SELECT * FROM tblTo ...
- 带你了解数据库中group by的用法
前言 本章主要介绍数据库中group by的用法,也是我们在使用数据库时非常基础的一个知识点.并且也会涉及Join的使用,关于Join的用法,可以看我写的上一篇文章:带你了解数据库中JOIN的用法如有 ...
- 转:深入研究mysql中group by与order by取分类最新时间内容
鉴于项目的需要,就从网上找到该文章,文章分析得很详细也很易懂,在android里, (不知道是不是现在水平的限制,总之我还没找到在用ContentProvider时可以使用子查询),主要方法是用SQL ...
- MySQL中INSERT的一般用法
原文链接:http://www.blogjava.net/midnightPigMan/archive/2014/12/15/421406.html MySQL中INSERT的一般用法 INSERT语 ...
- mysql 中find_in_set()和in()用法比较
mysql 中find_in_set()和in()用法比较 在mysql中in可以包括指定的数字,而find_in_set()用于特定的数据类型. find_in_set 函数使用方法 个例子来说:有 ...
- 深入研究mysql中group by与order by取分类最新时间内容
鉴于项目的需要,就从网上找到该文章,文章分析得很详细也很易懂,在android里,(不知道是不是现在水平的限制,总之我还没找到在用 ContentProvider时可以使用子查询),主要方法是用SQL ...
- oracle 中GROUP BY的用法
转自:http://blog.csdn.net/basenet855x/article/details/6694150 问题: select item.itemnum,item.in1,item.in ...
- MYSQL 中GROUP BY
group by 用法解析 group by语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表. SELECT子句中的列名必须为分组列或列函数.列函数对于GROUP BY子 ...
- MYSQL中replace into的用法以及与inset into的区别
在向表中插入数据时,我们经常会遇到这样的情况:1.首先判断数据是否存在:2.如果不存在,则插入:3.如果存在,则更新. 在SQL Server中可以这样处理: if not exists (selec ...
随机推荐
- Linux入门基础知识
注:内容系兄弟连Linux教程(百度传课:史上最牛的Linux视频教程)的学习笔记. Linux入门基础知识 1. Unix和Linux发展历史 二者就像父子关系,当然Unix是老爹.1965年,MI ...
- swift UITextView内容距离边框边距设置
des_textView.textContainerInset = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10) 设置对应的四个边距的值
- 白帽子之路首章:Footprinting, TARGET ACQUISITION
*Disclaimer: All materials provided on this blog are for educational purposes only. The author and o ...
- 响应式布局 —— Demo
响应式布局实例演示What is 响应式布局? 响应式布局是Ethan Marcotte在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端--而不是为每个终端做一个特定的版本.这 ...
- 序列化之protobuf与avro对比(Java)
最近在做socket通信中用到了关于序列化工具选型的问题,在调研过程中开始趋向于用protobuf,可以省去了编解码的过程.能够实现快速开发,且只需要维护一份协议文件即可. 但是调研过程中发现了pro ...
- YUM安装东西提示PYCURL ERROR 6 - "Couldn't错误的解决办法
执行yum install命令时提示PYCURL ERROR 6 - "Couldn't resolve host 错误,原来是dns设置出错,具体错误代码: Loaded plugins ...
- 关于JS中获取浏览器高度和宽度值的多种方法(多浏览器)
三种浏览器获取值方法 IE中: document.body.clientWidth ==> BODY对象宽度 document.body.clientHeight ==> BODY对象高度 ...
- leetcode range sum query
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive ...
- Python 字典和集合
泛映射类型 collections.abc 模块中有 Mapping 和 MutableMapping 这两个抽象基类,它们的作用是为 dict 和其他类似的类型定义形式接口(在Python 2.6 ...
- shell学习笔记(一)
1.第一行必须以#!/bin/bash #!表示脚本使用后面的解释器解释执行 2.echo 打印输出 例如 echo "hello world" > aa.txt 3.接 ...