MySQL 查询、聚合函数的使用


查询产生一个虚拟表,看到的是表形式显示的结果,但结果并不真正存储,每次执行查询只是现从数据表中提取数据,并按照表的形式显示出来。

1 SQL查询语句

1.1 select子句

使用以下几种方式指定字段列表:

字段列表说明
*字段列表为数据源的全部字段
表名*多表查询时,指定某个表的全部字段
字段列表指定所需要显示的列
  • 可以为字段列表中的字段名或表达式指定别名,中间使用as关键字分隔即可(as关键字可以省略)。
  • 多表查询时,同名字段前必须添加表名前缀,中间使用“.”分隔。

1.1 where子句

数据库中存储着海量数据,数据库用户往往需要的是满足特定条件的记录,where子句可以实现结果集的过滤筛选。

where 条件表达式
(1)条件表达式
关键字解释
比较运算符单一条件过滤
逻辑运算符组合多个条件查询
BETWEEN AND在两数之间
NOT BETWEEN AND不在两数之间
IN <值表>是否在特定的集合里(枚举)
NOT IN <值表> 与上面相反
LIKE是否匹配于一个模式
IS NULL为空的
IS NOT NULL不为空的
Binary区分大小写
比较运算符
  • 常用的比较运算符有=(等于)、>(大于)、>=(大于等于)、<(小于)、<=(小于等于)、<>(不等于)、!=(不等于)、!<(不小于)、!>(不大于)。
表达式1  比较运算符 表达式2
  • 说明:“表达式1”和“表达式2”可以是一个字段名、常量、变量、函数甚至是子查询。比较运算符用于比较两个表达式的值,比较的结果是一个布尔值(true或者false)。
  • 如果表达式的结果是数值,则按照数值的大小进行比较;如果表达式的结果是字符串,则需要参考字符序collation的设置进行比较
逻辑运算符

where子句中可以包含多个查询条件,使用逻辑运算符可以将多个查询条件组合起来,完成更为复杂的过滤筛选。

常用的逻辑运算符包括逻辑与(and)、逻辑或(or)以及逻辑非(not),其中逻辑非(not)为单目运算符。

  • 逻辑非(not或!)
    逻辑非(not)为单目运算符

  • and逻辑运算符使用and逻辑运算符连接两个布尔表达式时,只有两个布尔表达式的值都为true时,整个逻辑表达式的结果才为true。

  • 语法格式如下:布尔表达式1 and 布尔表达式2

  • or逻辑运算符or逻辑运算符连接两个布尔表达式时,只有两个表达式的值都为false时,整个逻辑表达式的结果才为false。
    语法格式如下:布尔表达式1 or 布尔表达式2

is (not) null运算符

is NULL用于判断表达式的值是否为空值NULL(is not 恰恰相反),is NULL的语法格式如下。

表达式 is null 
#说明:不能将“score is NULL”写成“score = NULL;”,
#原因是NULL是一个不确定的数,不能使用“=”、“!=”等比较运算符与NULL进行比较。
#例子
SELECT emp_name As 姓名, emp_address  AS 地址 
FROM EMPLOYEE 
WHERE emp_address IS NULL
between and

把某一字段中内容在特定范围内的记录查询出来

SELECT emp_name,emp_age 
FROM EMPLOYEE 
WHERE emp_age BETWEEN 20 AND 30
in

把某一字段中内容与所列出的查询内容列表匹配的记录查询出来

SELECT emp_name AS 员工姓名,emp_contry As 地址 
FROM EMPLOYEE 
WHERE emp_contry IN ('北京','广州','上海')
模糊查询(LIKE)

like运算符用于判断一个字符串是否与给定的模式相匹配。
模式是一种特殊的字符串,特殊之处在于不仅包含普通字符,还包含有通配符。
在实际应用中,如果不能对字符串进行精确查询,此时可以使用like运算符与通配符实现模糊查询,like运算符的语法格式如下。
字符串表达式 [ not ] like 模式

SELECT emp_name AS 姓名 
FROM EMPLOYEE 
WHERE emp_name LIKE '张%'
BINARY运算符

默认情况下,比较是不区分大小写的方式执行的。然而,以前我们注意到,可以添加BINARY关键字让MySQL执行区分大小写的比较。

SELECT * 
FROM emp 
WHERE empname  LIKE BINARY '%tom%';

2 聚合函数

工资表中存储了所有员工的工资,求:公司支出的总薪水、员工的平均工资、工资水平在2000块钱以上的总共有多少人?

2.1 SUM

SELECT SUM(sal_disburse) AS20095月公司总薪水支出’
FROM SALARY 
WHERE sal_ym=200905

2.2 AVG

SELECT AVG(sal_disburse) AS20096月平均工资’
FROM SALARY 
WHERE sal_ym=200906

2.3 MAX、MIN

SELECT AVG(sal_disburse) AS 平均工资,  MAX (sal_disburse) AS 最高工资,  MIN (sal_disburse) AS 最低工资 
FROM SALARY 
WHERE sal_ym =200911

2.4 COUNT

SELECT COUNT (*)  AS2000元工资以上的员工数量’
FROM SALARY 
WHERE sal_disburse>=2000
AND sal_ym=200907

3 完整的sql语句

select dept_id, count(*) from employee where dept_id is not null -- 对所有数据进行筛选,不能使用聚合函数
GROUP BY dept_id   -- 对where筛选后的数据进行分组
having count(*)>2  -- 对分组后的数据进行筛选
order by dept_id desc; -- 对数据进行排序

4 连接查询

学员内部测试成绩查询的每次显示的都是学员的编号信息,因为该表中只存储了学员的编号;实际上最好显示学员的姓名,而姓名存储在学员信息表;如何同时从这两个表中取得数据?

from 表名1  [ 连接类型 ]  join 表名2  on1和表2之间的连接条件

4.1 SQL连接分类

  • inner连接(内连接)
  • outer连接(外连接)
    left(左外连接,简称为左连接)
    right(右外连接,简称为右连接)
  • cross连接(交叉连接)

4.2 内连接 inner join

关键字:inner join on

#组合两个表中的记录,返回关联字段相符的记录,即返回两个表的交集部分
SELECT t1.name, t2.salary  
FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name;

4.3 左连接查询 left join

关键字:left join on / left outer join on

left join 是left outer join的简写,它的全称是左外连接,是外连接中的一种。 左(外)连接,左表(a_table)的记录将会全部表示出来,而右表(b_table)只会显示符合搜索条件的记录。右表记录不足的地方均为NULL

SELECT * 
FROM table1 
LEFT JOIN table2 ON table1.id = table2.id;

#多张表连接
SELECT * 
FROM table1 
LEFT JOIN table2 ON table1.id = table2.id
LEFT JOIN table3 ON table2.id = table3.id;

4.4 右连接查询 right join

关键字:right join on / right outer join on

说明:right join是right outer join的简写,它的全称是右外连接,是外连接中的一种。与左(外)连接相反,右(外)连接,左表(a_table)只会显示符合搜索条件的记录,而右表(b_table)的记录将会全部表示出来。左表记录不足的地方均为NULL。

SELECT * 
FROM table1 
LEFT JOIN table2 ON table1.id = table2.id;

4.5 交叉连接 cross join

在 MySQL 中JOIN,CROSS JOIN、 和INNER JOIN是句法是等价(它们可以相互替换)。在标准 SQL 中,它们不是等价的。

select * 
from employee e CROSS JOIN dept d on e.dept_id=d.dept_id;

#在mysql中等价于
select * 
from employee e INNER JOIN dept d on e.dept_id=d.dept_id;

#在mysql中等价于
select * 
from employee e,dept d where e.dept_id=d.dept;

5 子查询

出现在其他语句中的select语句,称为子查询或内查询。

在 MySQL 中,除了在 ORDER BY 列表中以外,在 SELECT、UPDATE、INSERT 和 DELETE 语句中任何可以使用表达式的地方都可以使用子查询来替代。

子查询特征

  • 子查询的 SELECT 查询总是使用圆括号括起来。
  • 子查询可以嵌套在外部 SELECT、INSERT、UPDATE 或 DELETE 语句的 WHERE 或 HAVING 子句内,或者其它子查询中。
  • 根据可用内存和查询中其它表达式的复杂程度不同,嵌套限制也有所不同,嵌套到 32 层。

5.1 子查询出现的位置

位置类型说明
select后面仅仅支持标量子查询做为一个字段值
from后面支持表子查询做为一个临时表
where 或 having后面 支持标量子查询(单行)、列子查询(多行)、行子查询做为过滤条件
exists后面(也被称为相关子查询)支持表子查询
  • 标量子查询:结果集为一行一列
  • 列子查询:结果集为一列多行
  • 行子查询:结果集为一行多列
  • 表子查询:结果集为多行多列

HERE 包括子查询的语句通常采用以下格式中的一种:

  • WHERE 表达式 比较运算符 (子查询)
  • WHERE 表达式 [NOT] IN (子查询)
  • WHERE [NOT] EXISTS (子查询)

5.2 比较运算符(子查询)

子查询可由一个比较运算符(=、< >、>、> =、<、!>, ! < 或 < =)引入。要使用由比较运算符引入的子查询,必须对数据和问题的本质非常熟悉,以了解该子查询实际是否只返回一个值。

--示例:取出所有大于平均工资的所有员工信息
select * 
from employee 
where emp_salary > (select avg(emp_salary) from employee);

5.3 IN子查询

通过 IN(或 NOT IN)引入的子查询结果是一列零值或更多值。子查询返回结果之后,外部查询将利用这些结果。

--示例:显示部门为销售部和研发部,并且年龄为22岁的员工的所有信息
select * 
from employee where emp_age=22 and dept_id in (select dept_id from dept where dept_name='销售部' or dept_name='研发部')

5.4 EXISTS子查询

使用 EXISTS 关键字引入一个子查询时,就相当于进行一次存在测试。外部查询的 WHERE 子句测试子查询返回的行是否存在。子查询实际上不产生任何数据;它只返回 TRUE 或 FALSE 值。 使用 EXISTS 引入的子查询在以下几方面与其它子查询略有不同,EXISTS 关键字前面没有列名、常量或其它表达式。

-- 如果存储部位1004,则显示所有员工信息
SELECT * 
FROM employee WHERE EXISTS (SELECT d_name FROM department WHERE d_id=1004);
--如果此处内层循环并没有查询到满足条件的结果,则返回false,外层查询不执行

6 MySQL分页

MySQL数据库实现分页比较简单,提供了LIMIT函数。一般只需要直接写到sql语句后面就行了。

6.1 分页实现

select字段列表
from数据源
limit [start,]length;
--start表示从第几行记录开始检索,length表示检索多少行记录。表中第一行记录的start值为0。

--例子
select * 
from table WHERELIMIT 10; #返回前10行
--上sql语句等效于
select * 
from table WHERELIMIT 0,10; #返回前10行 
select * 
from table WHERELIMIT 10,10; #返回第10-20行数据 

6.2 分页优化(扩展)

问题:对于limit 10000,20的意思扫描满足条件的10020行,扔掉前面的10000行,返回最后的20行。如果是limit 100000,100,需要扫描100100行,在一个高并发的应用里,每次查询需要扫描超过10W行,性能肯定大打折扣。limit n性能是没问题的,因为只扫描n行。
优化解决办法:

SELECT * 
FROM message 
WHERE id>=1000 ORDER BY id ASC LIMIT 20;//当前页

SELECT * 
FROM message 
WHERE id>1020 ORDER BY id ASC LIMIT 20;//下一页

SELECT * 
FROM message 
WHERE id<1000 ORDER BY id DESC LIMIT 20;//上一页
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值