mysql学习(二)-Group by与having理解

注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里。

一. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用

group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面(重要)

例如,有如下数据库表:

A B
1 ABC
1 BCD
1 ASDFG

如果有如下查询语句(该语句是错误的,原因见前面的原则)

1 select A,B from table group by A  

该查询语句的意图是想得到如下结果(当然只是一相情愿)

A     B 
       abc 
1     bcd

asdfg

右边3条如何变成一条,所以需要用到聚合函数,如下(下面是正确的写法):

1 select A,count(B) as 数量 from table group by A 

这样的结果就是

A 数量
1 3

二、 Having

where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。

having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。

having 子句被限制子已经在SELECT语句中定义的列和聚合表达式上。通常,你需要通过在HAVING子句中重复聚合函数表达式来引用聚合值,就如你在SELECT语句中做的那样。例如:

1 SELECT A COUNT(B) FROM TABLE GROUP BY A HAVING COUNT(B)>2

三、使用compute和compute by

  • 使用compute子句允许同时观察查询所得到各列的数据的细节以及统计各列数据所产生的汇总列
  •   select * from work [查询所得到的各列的数据的细节]
  •    compute max(基本工资),min(基本工资) [统计之后的结果]
  • 这个例子中没有使用by关键字,返回的结果是最后添加了一行基本工资的最大值和最小值,也可增加by关键字.
  • 例:   select * from work order by 学历
  • compute max(基本工资),min(基本工资) by 学历
  • 比较:select 学历,max(基本工资),min(基本工资) from work group by 学历
  • 说明:1:compute子句必须与order by子句用在一起
  • 2:compute子句可以返回多种结果集.一种是体现数据细节的数据集,可以按分类要求进行正确的分类;另一种在分类的基础上进行汇总产生结果.
  • 3:而group by子句对每一类数据分类之后只能产生一个结果,不能知道细节


非相关查询:

1:返回每个美国员工都为其处理过订单的所有客户

--思路:1:Employees表中获取美国员工总数2:Orders表中查询美国员工处理的Order,对CustomerID分组后,统计其不同的EmployeeID正好等于美国员工总数

Select
    CustomerID
From
    Orders
Where
    EmployeeID In -- 得到美国员工服务 的客户 (
        Select
            EmployeeID
        From
            Employees
        Where
            Country = N‘USA‘
    ) -- 得到全部美国员工id
group by
    CustomerID -- 按客户分组
Having
    Count(Distinct EmployeeID) = -- 为其处理订单的distinct 员工数等于美国总员工数 (
        Select
            Count(*)
        From
            Employees
        Where
            Country = N‘USA‘
    ) -- 美国员工总数

2:

返回在每月最后实际订单日期发生的订单(每月最后订单日期可能不是每月最后一天)

--思路:子查询按月分组得到每月最近订单日期

Select
    OrderID,
    CustomerID,
    EmployeeID,
    OrderDate
From
    Orders
Where
    OrderDate In (
        Select
            Max(OrderDate)
        From
            Orders
        Group by
            Convert (char(6), OrderDate, 112)
    ) -- 112表示YYYYMMDD char (6) 提取YYYYMM

3.

Select字句在逻辑上是SQL语句最后进行处理的最后一步,所以,以下查询会发生错误:

SELECT
    OrderYear,
    COUNT(DISTINCT CustomerID) AS NumCusts
FROM
    (
        SELECT
            YEAR (OrderDate) AS OrderYear,
            CustomerID
        FROM
            dbo.Orders
    ) AS D
GROUP BY
    OrderYear

因为group by是在Select之前进行的,那个时候orderYear这个列并没有形成。

如果要查询成功,可以像下面进行修改:

SELECT
    OrderYear,
    COUNT(DISTINCT CustomerID) AS NumCusts
FROM
    (
        SELECT
            YEAR (OrderDate) AS OrderYear,
            CustomerID
        FROM
            dbo.Orders
    ) AS D
GROUP BY
    OrderYear

还有一种很特殊的写法:

SELECT
    OrderYear,
    COUNT(DISTINCT CustomerID) AS NumCusts
FROM
    (
        SELECT
            YEAR (OrderDate),
            CustomerID
        FROM
            dbo.Orders
    ) AS D (OrderYear, CustomerID)
GROUP BY
    OrderYear

这种写法的,因为更清晰,更明确,更便于维护。

在查询中使用参数定向产生一批结果,这个技巧没有什么好说的。

嵌套查询,在处理逻辑上是从里向外进行执行的。

时间: 2024-10-23 21:09:12

mysql学习(二)-Group by与having理解的相关文章

MySql学习(二) —— where / having / group by / order by / limit 简单查询

这篇博客主要记录sql的五种子句查询语法! 一个重要的概念:将字段当做变量看,无论是条件,还是函数,或者查出来的字段. select五种子句 where 条件查询 group by 分组 having 筛选 order by 排序 limit 限制结果条数 为了练习上面5种子句,先建立一张goods表,主要用于查询操作,表结构如下: 1.基础查询 —— where where常用运算符: 1.1 查出主键为20的商品 :mysql> SELECT goods_id,cat_id,goods_sn

MySQL学习(二)——SQL语句创建删除修改以及中文乱码问题

一.对数据库的操作 1.创建一个库 create database 库名; 创建带有编码的:create database 库名 character set 编码; 查看编码:show create database 库名; 2.删除一个库 drop database 库名; 3.使用库 use 库名; 4.查看当前正在操作的库 select database(); 二.对数据库表的操作 1.创建一张表 create table 表名( 字段名 类型(长度) [约束], 字段名 类型(长度) [

mysql学习(一)-group by的使用

业务场景一:查询主表并带出与主表关联的子表的个数 实现方法:分组group by 子表外键 sql如下: 1 select 2 main.id id, 3 main.name name, 4 IFNULL(sub.num,'0') num 5 from 6 xx_main main 7 left join( 8 select count(1) num,main_id from xx_sub group by main_id 9 )sub ON main.id = sub.main_id 10 w

MYSQL学习(二)

并发控制 MySQL在两个层面实现并发控制:服务器层与存储引擎层. 读锁和写锁: 在处理并发读或写时,可以通过实现一个由两种锁组成的系统来解决问题. 这两种锁通常被称为共享锁和排他锁,或者称为读锁和写锁. 读锁:是共享的,或者说是相互不阻塞的,多个客户可以在同时读取同一数据. 写锁:是排他的,一个写锁会阻塞其他的写锁和读锁,同一时刻只能有一个用户能够写入,并防止其他用户读取正在写入的数据. 锁粒度: 锁粒度:指加锁的对象的大小.显然,锁的粒度越小,并发控制效率越高. 锁的各种操作,包括获得锁.检

MySQL学习(二)——MySQL多表

分页操作:使用limit(参数1,参数2) 起始位置(参数1)=(第几页-1)*每页显示的条数(参数2) 1.分类表 create table category( cid varchar(32) primary key, cname varchar(100) ); 2.商品表 create table product( pid varchar(32) primary key, pname varchar(40), price double, category_id varchar(32) );

MYSQL学习二 关于左连接

工作中有如下的SQL, 针对A.ID ='abcdefg', left  join  B和C两个表,来查找其他信息.就算是B和C中没有任何满足条件的记录,最后结果也肯定不是空.因为A.ID ='abcdefg'是存在的. SELECT ****** FROM tableA A LEFT JOIN tableB B on b.DELETED = '0' AND A.DELETED = '0' AND B.fid=A.ID LEFT JOIN tableC C ON B.XXXid=C.id AND

我的MYSQL学习心得(十二)

原文:我的MYSQL学习心得(十二) 我的MYSQL学习心得(十二) 我的MYSQL学习心得(一) 我的MYSQL学习心得(二) 我的MYSQL学习心得(三) 我的MYSQL学习心得(四) 我的MYSQL学习心得(五) 我的MYSQL学习心得(六) 我的MYSQL学习心得(七) 我的MYSQL学习心得(八) 我的MYSQL学习心得(九) 我的MYSQL学习心得(十) 我的MYSQL学习心得(十一) 这一篇<我的MYSQL学习心得(二)>将会讲解MYSQL的触发器 触发器是一个特殊的存储过程,不

mysql学习之二:mysql基本用法

安装完mysql后我们可以进行sql语句的操作: 我们可以使用以下命令连接到MySQL服务: mysql -h localhost -u root -p -h参数指定要连接的MySQL服务器地址 -u参数指定连接所使用的用户 -p参数指定使用密码验证登陆 MySQL服务绝大多数功能使用SQL语言进行管理. SQL语言一般约定俗成使用大写,但是语言本身不限制大小写.几乎所有SQL语句都必须以";"结尾. 列出所有数据库: SHOW DATABASES; 创建一个数据库(linuxcast

MySQL命令学习(二)

(13)where字句操作符 =            等于 <>          不等于 !=           不等于 <            小于 >            大于 >=          大于等于 BETWEEN          在指定的两个值之间 例如: 找出学号是0007到0009之间的学生记录(不包括0009)? SELECT* FROM student_info WHERE stu_id BETWEEN 1001101620007 AND

我的MYSQL学习心得(二)

原文:我的MYSQL学习心得(二) 我的MYSQL学习心得(二) 我的MYSQL学习心得(一) 我的MYSQL学习心得(三) 我的MYSQL学习心得(四) 我的MYSQL学习心得(五) 我的MYSQL学习心得(六) 显示宽度 MYSQL中的整数型数据类型都可以指定显示宽度,而SQLSERVER不行 创建一个表 CREATE TABLE tb_emp( id BIGINT(1)) id字段的数据类型为BIGINT(1),注意到后面的数字1,这表示的是该数据类型指定的显示宽度,指定能够显示的数值中数