MySQL 数据查询语言Data Query Language

MySQL基础知识

基础概念

主键需要满足的条件

1.任意两行都不具有相同的主键值
2.每一行都必须具有一个主键值且不能为NULL
3.主键列中的值不允许修改或更新
4.主键不能重用,如果某行从表中删除,它的主键也不能赋给以后的新行。

DB、DBMS、SQL

DB(database)数据库:存储数据的'仓库',保存了一系列有组织的数据
DBMS(Database Management System)数据库管理系统:用于创建或管理DB
SQL(Structure Query Language):结构化查询语言,专门用来与数据库通信的语言

SQL特性

  1. 多条SQL必须以分号结尾,多数DBMS不需要在单条SQL语句后面加分号,但有些单条SQL语句后必须加,所以建议都加上。
  2. 处理SQL语句时,其中所有空格都会被忽略。
  • MySQL 在 Windows 环境下是大小写不敏感的
  • MySQL 在 Linux 环境下是大小写敏感的
    • 数据库名、表名、表的别名、变量名是严格区分大小写的
    • 关键字、函数名、列名(或字段名)、列的别名(字段的别名) 是忽略大小写的。
  • 推荐采用统一的书写规范:
    • 数据库名、表名、表别名、字段名、字段别名等都小写
    • SQL 关键字、函数名、绑定变量等都大写

SQL分类

  • DDL(Data Definition Languages、数据定义语言这些语句定义了不同的数据库、表、视图、索引等数据库对象,还可以用来创建、删除、修改数据库和数据表的结构。
    • 主要的语句关键字包括CREATEDROPALTER等。
  • DML(Data Manipulation Language、数据操作语言),用于添加、删除、更新和查询数据库记录,并检查数据完整性。
    • 主要的语句关键字包括INSERTDELETEUPDATESELECT等。
    • SELECT是SQL语言的基础,最为重要。
  • DCL(Data Control Language、数据控制语言),用于定义数据库、表、字段、用户的访问权限和安全级别。
    • 主要的语句关键字包括GRANTREVOKECOMMITROLLBACKSAVEPOINT等。

因为查询语句使用的非常的频繁,所以很多人把查询语句单拎出来一类:DQL(数据查询语言)。
还有单独将COMMITROLLBACK 取出来称为TCL (Transaction Control Language,事务控制语言)。

注释

单行注释:#注释文字(MySQL特有的方式)
单行注释:-- 注释文字(--后面必须包含一个空格。)
多行注释:/* 注释文字  */

DQL数据查询语言(Data Query Language)

基础查询

语法:SELECT 查询列1,查询列2.. FROM 表名;

输出所有列:SELECT * FROM 表名;

# 基础查询 
USE myemployees;
# 1.查询表中的单个字段
SELECT last_name FROM employees;

# 2.查询表中的多个字段
SELECT last_name,salary,email FROM employees;

# 3.查询表中的所有字段
# 方式一:使用*输出的顺序和原始表的顺序一样
SELECT * FROM employees;

# 方式二:可以自定义顺序
SELECT 
  `first_name`,
  `last_name`,
  `email`,
  `phone_number`,
  `manager_id`,
  `salary`,
  `job_id`,
  `department_id`,
  `hiredate`,
  `commission_pct`
FROM
   employees;
类型 关键字 案例 说明
去重 DISTINCT SELECT DISTINCT department_id FROM employees; DISTINCT 需要放到所有列名的前面,不支持部分去重,对后面所有列名的组合进行去重
重命名一个列 AS 别名 SELECT a AS b FROM user_profile 如果别名中包含空格或特殊的字符并区分大小写时,可以加双引号,
AS可以省略但不建议
输出的是别名
着重号 用``框起来 SELECT * FROM ORDER; 我们需要保证表中的字段、表名等没有和保留字、数据库系统或常用方法冲突。如果真的相同,使用着重号框起来。

说明
1.mysql中,单引号和双引号都可以表示字符串,没有区别
2.mysql的别名可以不加引号,如果加引号防止有空格等识别不出来,单引号和双引号以及反引号都可以
3.mysql的字段名、表名通常不需要加任何引号,如果非要加上引号,必须加反引号

查询常数

SELECT 查询还可以对常数进行查询。就是在 SELECT 查询结果中增加一列固定的常数列。这列的取值是我们指定的,而不是从数据表中动态取出的。

为什么我们还要对常数进行查询呢?

一般来说我们只从一个表中查询数据,通常不需要增加一个固定的常数列,但如果我们想整合不同的数据源,用常数列作为这个表的标记,就需要查询常数。

比如说,我们想对 USER 数据表中的员工姓名进行查询,同时增加一列字段 corporation ,这个字段固定值为"TX"

SELECT 'TX' AS corporation, NAME
FROM USER;

image

拼接函数concat/为空设置默认值函数 IFNULL

concat(参数1,参数2....) 拼接参数列表
IFNULL(表达式,默认值) 判断是否为NULL,如果为NULL使用默认值

# 查询员工名和姓连接成一个字段,并显示为姓名
SELECT CONCAT(last_name,first_name) AS 姓名 FROM employees;
SELECT  CONCAT(last_name,",",first_name,",",IFNULL(commission_pct,0)) AS out_put FROM employees;

条件查询 WHERE子句

SELECT 字段1,字段2 FROM 表名 WHERE 过滤条件

WHERE子句紧跟FROM子句

分类
1.按条件表达式筛选(> < = !=/<> >= <=)
2.按逻辑表达式筛选(&&/and ||/or !/not)
3.模糊查询(like, between and, in, is null)

比较运算符

1.比较运算符用来对表达式左边的操作数和右边的操作数进行比较,比较的结果为真则返回1,比较的结果为假则返回0,其他情况则返回NULL
2.所有运算符或列值遇到null值,运算的结果都为null,在 MySQL 里面, 空值不等于空字符串。一个空字符串的长度是 0,而一个空值的长度是空。而且,在 MySQL 里面,空值是占用空间的。

操作符 说明 NULL值
= 1.字符串比较每个字符的ANSI编码是否相等
2.如果等号两边的值一个是整数,另一个是字符串,则MySQL会将字符串转化为数字进行比较。
不能判断NULL,意思是有NULL结果就为NULL
<=> 安全等于,对NULL值处理不一样,其他返回结果与等于运算符相同 可以判断NULL和其他值,结果为0。如果两边都是NULL,结果为1
<>/!= 不等于 不能判断NULL
</<= 小于与大于等于 不能判断NULL
>/>= 大于与大于等于 不能判断NULL

逻辑运算符

运算符 作用
NOT 或 ! 逻辑非 否定跟着它后面的条件
AND 或 && 逻辑与
OR 或
XOR 逻辑异或(偶数个1)

image

IS NULL为空运算符/IS NOT NULL不为空运算符

是否可以判断NULL

类型 普通类型的数值 null型
赋值 =/!= ×
关键字 is ×
安全等于 <=>
IS NULL ISNULL(参数)
IS关键字,判断是否为NULL ISNULL(参数) 是一个函数,判断参数是否为空,返回函数结果1真0假
IS NOT NULL,判断不为空 NOT ISNULL(参数),意思是对ISNULL的
# 模糊查询
# 判断为空
SELECT last_name ,commission_pct FROM employees WHERE commission_pct IS NULL ;
SELECT employee_id,commission_pct FROM employees WHERE ISNULL(commission_pct);

# 判断不为空
SELECT employee_id,commission_pct FROMemployees WHERE NOT ISNULL(commission_pct);
SELECT employee_id,commission_pct FROMemployees WHERE commission_pct IS NOT NULL;

BETWEEN AND 两值之间运算符

betwenn相当于>= and相当于<=

注意事项
1.包含临界值
2.顺序不能乱

# 查询员工编号在100到120之间的员工信息
SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120;

IN属于运算符/NOT IN不属于运算符

mysql> SELECT 'a' IN ('a','b','c'), 1 IN (2,3), NULL IN ('a','b'), 'a' IN ('a', NULL);
+----------------------+------------+-------------------+--------------------+
| 'a' IN ('a','b','c') | 1 IN (2,3) | NULL IN ('a','b') | 'a' IN ('a', NULL) |
+----------------------+------------+-------------------+--------------------+
| 1 | 0 | NULL | 1 |
+----------------------+------------+-------------------+--------------------+

IN 和 OR实现的相同功能

  1. IN的执行速度比OR快
  2. IN 后面可以跟SELECT子句
WHERE manager_id IN (100, 101);
WHERE manager_id=100 OR managerid_id=101;

like 模糊匹配运算符

语法: like 搜索模式
搜索模式:由字面值、通配符或两者组合构成的搜索条件

说明
1.一般和通配符搭配使用,
2.

通配符 说明
% 代表零个或多个字符
不可以匹配NULL
_ 任意单个字符

3.ESCAPE关键字 自定义转移符
4.可以判断数值型和字符型,都写在引号里

通配符的使用注意
1.通配符搜索的处理比较慢,其他操作符能够达到相同的效果,尽量使用其他操作符
2.尽量不要放在搜索模式的开头处,搜索起来最慢

# 模糊查询
# 1.查询员工名中包含字符a(模糊条件)的员工信息
SELECT * FROM employees WHERE last_name LIKE '%a%';

# 2.查询员工名中第三个字符为e,第五个字符为a的员工名和工资
SELECT last_name,salary 
FROM employees
WHERE	last_name LIKE '__e_a%';

# 3.查询员工名中第二个字符为_的员工名 
# 方法一:\转义字符
# 方法二:ESCAPE关键字 自定义转移符
SELECT last_name
FROM employees
# where last_name LIKE '_\_%'、
WHERE last_name LIKE '_S_%' ESCAPE 'S';

REGEXP 正则运算符

REGEXP运算符用来匹配字符串,语法格式为: expr REGEXP [BINARY] '匹配条件'
BINARY:MySQL中的正则表达式匹配不区分大小写,该关键字的意思是区别大小写

正则表达式的使用

多数正则表达式实现使用单个反斜杠转义特殊字符,但MySQL需要两个反斜杠,MySQL自己解释一个,正则表达式库解释另一个

聚集函数

Mysql的聚合函数不支持嵌套使用
聚集函数:对一组数据进行汇总,输入的是一组数据的集合,输出的是单个值。

语法:selsect 函数名([DISTINCT] 参数) [from 表]
1.函数中的参数使用到了表中属性时需要添加form表
2.DISTINCT 可选,表示对参数去重,把不同的参数作为输入。只能作用于参数指定了列名的函数,COUNT(DISTINCT *)不可以使用。

使用案例

  • 确定表中的总行数、符合条件的行数
  • 获取表中行组的和
  • 找出最大值、最小值、平均值
函数 说明 作用范围 是否忽略NULL
AVG() 返回某列的平均值 对数值型数据使用
SUM() 返回之和 对数值型数据使用
MAX() 返回最大值 对任意数据类型使用,如果是文本数据,返回最后面的
MIN() 返回最小值 对任意数据类型使用,如果是文本数据,返回最前面的
COUNT() COUNT(*)返回表中记录总数,
COUNT(column)对特定的列中具有值得行进行计数
COUNT(1或者其他常数值)相当于多了列,一列全部是常数值
对任意数据类型使用 COUNT(*) ×
COUNT(column) √
COUNT(1或者其他常数值) √

问题:用count(*),count(1),count(列名)谁好呢?

其实,对于MyISAM引擎的表是没有区别的。这种引擎内部有一计数器在维护着行数。
Innodb引擎的表用count(*),count(1)直接读行数,复杂度是O (n),因为innodb真的要去数一遍。COUNT(*) = COUNT(1)>COUNT(列名)。

分组GROUP BY 和 HAVING

语法
SElECT 分组之后执行的函数[,列]
FROM table
[where condition]
[group by group_by_expression]
[order by 子句];

注意:

1.group by 的位置必须在where子句之后,order by 子句之前。
2.这里的列如果有,只能是在分组条件中出现的列,否则分组之后的行数,和这里写的列选出来的行数不一样。

单个列分组

案例:查询每个工种的最高工资 (分组条件每个工种)

SELECT MAX(salary)[,job_id] # 为了方法查看最高工资是哪个job_id可以写出来
FROM employees
GROUP BY job_id;

多个列分组

案例:查询每个部门(不为null)每个工种的员工的平均工资,并按平均工资的高低显示 (分组条件部门和工种)

多个字段之间用逗号隔开并没有顺序要求

SELECT AVG(salary) 平均工资[,department_id,job_id] # 基于可读性加上了
FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id,job_id
ORDER BY 平均工资 DESC;

SELECT 中出现的非组函数的字段必须声明在GROUP BY 中

# 按department_id分组,一个部门占一行数据
# 这个一个部门里面有好几种job_id,那么应该选哪一个呢???
# 这个是错误写法
SELECT AVG(salary) 平均工资,department_id,job_id
FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id;

WITH ROLLUP

作用:在所有查询出的分组记录之后,添加一条记录,该记录把分组之后的记录当作输入再执行一次聚合函数

SELECT MAX(salary),job_id
FROM employees
GROUP BY job_id WITH ROLLUP;

# job_id MAX(salary)
# ...
# NULL  把结果MAX(salary)列看成一组,找出其中最高的
# 如果是avg函数,相当于所有的平均值再求一次平局

分组过滤 HAVING

案例1:查询各个部分中最高工资比10000高的部门信息

# 错误写法
SELECT MAX(salary) ,department_id
FROM employees
WHERE MAX(salary)>10000;
GROUP BY department_id;

为什么错误?
WHERE比分组先执行

HAVING注意点
1.如果过滤条件中使用了聚合函数,必须使用HAVING
2.HAVING 必须声明在GROUP BY后面
3.开发中,使用HAVING的前提是GROUP BY使用。(可单独使用但是不推荐)

# 正确写法
SELECT MAX(salary) ,department_id
FROM employees
GROUP BY department_id;
HAVING MAX(salary)>10000;

案例2:查询部门id为10,20这2个部门中最高工资比10000高的部分信息。

# 方式1 推荐:执行效率更高
SELECT MAX(salary) ,department_id
FROM employees
WHERE department_id IN (10,20)
GROUP BY department_id;
HAVING MAX(salary)>10000;

# 方式2
SELECT MAX(salary) ,department_id
FROM employees
GROUP BY department_id;
HAVING MAX(salary)>10000 AND  department_id IN (10,20);

方式1在执行基础查询的时候只选出了department_id为10或20的数据进行分组。先筛选再分组
方式2在查询出了所有department_id的数据,最后选出了department_id为10或20的数据。先分组再筛选

WHERE与HAVING的对比
-|优点|缺点
WHERE|先筛选再关联,执行效率高|不能使用分组中的计算函数作为过滤条件,WHERE没有分组的概念
HAVING|可以使用分组中的计算函数为条件|先分组再筛选,执行效率低

排序 ORDER BY子句

使用 ORDER BY 子句排序
语法:ORDER BY xxx[ASC/DESC],yyy [ASC/DESC] ;
ASC(ascend): 升序,默认
DESC(descend):降序

知识点:
1.支持多个字段排序,先按第一个排,第一个相同按第二个排
2.order by 子句一般放在查询语句最后。limit子句除外

LIMIT

限制返回条数
语法
LIMIT x,y x默认0(可省略),返回从x开始的y条数据
LIMIT x OFFSET y 从x开始取y行

说明:
LIMIT 子句必须放在整个SELECT语句的最后

案例:分页显示公式

# PageNo是当前页数,PageSize是每页的大小
LIMIT(PageNo - 1)\*PageSize,PageSize;

案例:与LIMIT结合,找最大/小

# 找到最贵的
SELECT prod_price
FROM products
ORDER BY prod_price DESC
LIMIT 1;

多表查询

通常使用sql99标准

等值与非等值:
等值连接:连接条件 等号
非等值连接:连接条件 不是等号

自连接与非自连接:
自连接:多表是指自己与自己
使用场景:同一张表需要查询两遍

内连接与非内连接
内连接:只取交集

注意点:

1.给表起了别名之后,原名就被覆盖了,之后使用都使用别名。
2.建议:从sql优化的角度,建议多表查询时,每个字段前都指明所在的表

UNION 合并查询

把多条SELECT语句的结果组合成单个结果集。
每个表对应的列数和数据类型必须相同,并对应。

语法:
SELECT .. FROM t1
UNION [ALL]
SELECT .. FROM t2

  • UNION: A ∪ B 会自动去重
  • UNION ALL: A ∪ B 不会去重,显示所有

执行UNION ALL语句时所需要的资源比UNION语句少。如果明确知道合并数据后的结果数据不存在重复数据,或者不需要去除重复的数据,则尽量使用UNION ALL语句,以提高数据查询的效率。

/*
案例:查看学校为山东大学或者性别为男性的用户的device_id、gender、age和gpa数据,请取出相应结果,结果不去重。
*/
SELECT device_id,gender,age,gpa
FROM user_profile
WHERE university = "山东大学" OR gender="male"; # 默认去重,一行又是male又是山东大学只会被匹配一次

# 不去重写法
SELECT device_id,gender,age,gpa
FROM user_profile
WHERE university = "山东大学" # 一行又是male又是山东大学这里匹配一次
UNION ALL
SELECT device_id,gender,age,gpa
FROM user_profile
WHERE gender = "male"; # 一行又是male又是山东大学这里又匹配一次

sql92语法

等值连接

说明:where后面添加连接条件

笛卡尔积:A表每一行都和B表的所有行匹配过

/*
sql92内连接写法如下,mysql不支持sql92外连接写法
案例1:查询员工名、工种号、工种名
*/
SELECT last_name,e.`job_id`,job_title
FROM employees e,jobs j
WHERE e.`job_id` = j.`job_id`;

# 有筛选条件使用and
/*
案例2.查询有奖金的员工名,部门名
*/
SELECT last_name,department_name
FROM employees e,departments d
WHERE e.`department_id` = d.`department_id`
AND commission_pct IS NOT NULL;

自连接和非自连接

自连接:多表是指自己与自己
使用场景:同一张表需要查询两遍

/*
案例1:查询员工名和上级的名称  同一张表需要寻找两遍
第一遍找员工的领导编号是是多少,第二遍找这个编号对应的人是谁
*/
SELECT 
  e.employee_id 员工编号,
  e.last_name 员工名,
  m.employee_id 领导编号,
  m.last_name 领导名
FROM
  employees e,employees m
WHERE m.employee_id =e.manager_id;

SQL99标准

  • 内连接:用第一张的表的一行去匹配第二张表的每一行,匹配成功则留下来 --只取交集A∩B
  • 外连接 一般题目有:所有
    • 左外连接,除了交集还多包含了左表中不匹配的行 --AU(A∩B),左表为主表
    • 右外连接,除了交集还多包含了右表中不匹配的行 --(A∩B)UB,右表为主表
    • 全连接,AUB

sql99标准

select 查询列表
from 表1 别名
[连接类型] join 表2 别名
on 连接条件

连接类型 含义 案例
内连接 AuB FROM A [inner] JOIN B ON
左外连接 AU(A∩B) FROM A LEFT JOIN B ON
右外连接 (A∩B)UB FROM A RIGHt JOIN B ON
全连接 AUB FROM A FULL JOIN B ON(mysql不支持)

image

SQL99新特性1-自然连接NATURAL JOIN

自动查询两张表中所有相同字段,不用指出来,然后进行等值连接

# SQL92标准中
SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.`department_id` = d.`department_id`
AND e.`manager_id` = d.`manager_id`;

# SQL99中
SELECT employee_id,last_name,department_name
FROM employees e NATURAL JOIN departments d;

SQL99新特性2-USING连接

USING() 在一下情况可以代替 ON

SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
ON e.department_id = d.department_id; //语句1

SELECT employee_id,last_name,department_name
FROM employees e JOIN departments d
USING (department_id) # 当字段名一样的时候,可以用这句替换语句1

子查询

子查询的基本使用

  • 子查询(内查询)在主查询之前一次执行完成。
  • 子查询的结果被主查询(外查询)使用 。

注意事项

  • 子查询要包含在括号内
  • 将子查询放在比较条件的右侧
  • 单行操作符对应单行子查询,多行操作符对应多行子查询

子查询的分类

从子查询返回的结果的条目数

  • 单行子查询,子查询值返回一行
  • 多行子查询,子查询值返回多行

从内查询是否被执行多次

  • 相关子查询:案例查询工资大于本部门平均工资的员工信息,子查询结果随着员工的部门改变。
  • 不相关子查询:子查询的结果固定?和主查询没有相关性

子查询的位置
除了GROUP BY和LIMIT之外都可以使用

单行子查询

操作符 含义
= equal to

|greater than
= |greater than or equal to
< |less than
<= |less than or equal to
<> |not equal to

子查询编写技巧:①从里往外写 ②从外往里写

案例1:查询与141号或174号员工的manager_id和department_id相同的其他员工的employee_id,
manager_id,department_id

# 不成对比较
SELECT employee_id, manager_id, department_id
FROM employees
WHERE manager_id IN
  (SELECT manager_id
  FROM employees
  WHERE employee_id IN (174,141))
AND department_id IN
   (SELECT department_id
    FROM employees
    WHERE employee_id IN (174,141))
AND employee_id NOT IN(174,141);

# 成对比较,了解
SELECT employee_id, manager_id, department_id
FROM employees
WHERE (manager_id, department_id) IN
    (SELECT manager_id, department_id
     FROM employees
    WHERE employee_id IN (141,174))  
AND employee_id NOT IN (141,174);

多行子查询

操作符 含义
IN 等于列表中的任意一个
ANY 需要和单行比较操作符一起使用,和子查询返回的某一个值比较成功
ALL 需要和单行比较操作符一起使用,和子查询返回的所有值比较成功
SOME 实际上是ANY的别名,作用相同,一般常使用ANY

案例1:查询最低的平均工资

# MySQL中的聚合函数是不能嵌套使用
SELECT MIN(sav_sal)
FROM(
  SELECT AVG(salary) avg_sal
  FROM employees
  GROUP BY depatment_id
) t # 必须给表起别名,不然是个无名表

# 方式2
SELECT AVG(salary) avg_sal
FROM employees
GROUP BY depatment_id
ORDER BY avg_sal
LIMIT 1;

相关子查询

如果子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件
关联,因此每执行一次外部查询,子查询都要重新计算一次,这样的子查询就称之为 关联子查询 。
相关子查询按照一行接一行的顺序执行,主查询的每一行都送给子查询并执行一次子查询。

子查询中使用主查询中的列
案例1:查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id


uploading-image-506667.png

** EXISTS 与 NOT EXISTS关键字**

  • 关联子查询通常也会和 EXISTS操作符一起来使用,用来检查在子查询中是否存在满足条件的行。
  • 如果在子查询中不存在满足条件的行
    • 条件返回 FALSE
    • 继续在子查询中查找
  • 如果在子查询中存在满足条件的行:
    • 不在子查询中继续查找
    • 条件返回 TRUE

题目中可以使用子查询,也可以使用自连接。一般情况建议你使用自连接,因为在许多 DBMS 的处理过
程中,对于自连接的处理速度要比子查询快得多。
可以这样理解:子查询实际上是通过未知表进行查询后的条件判断,而自连接是通过已知的自身数据表
进行条件判断,因此在大部分 DBMS 中都对自连接处理进行了优化。

执行顺序

SELECT子句的顺序

子句 说明 是否必须使用
SElECT
FROM 仅在表中选择数据时使用
where 行级过滤
必须紧跟FROM
×
group by 必须在order by与where之间 仅在按组计算聚集时使用
HAVING 组级过滤
HAVING必须紧跟GROUP BY
×
order by 一般放最后面,有LIMIT就倒数第二 ×
Limit 必须放在最后 ×
# sql92语法
SELECT ...,....,...
FROM ...,...,....
WHERE 多表的连接条件
AND 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...

# sql99语法
SELECT ...,....,...
FROM ... JOIN ...
ON 多表的连接条件
JOIN ...
ON ...
WHERE 不包含组函数的过滤条件
AND/OR 不包含组函数的过滤条件
GROUP BY ...,...
HAVING 包含组函数的过滤条件
ORDER BY ... ASC/DESC
LIMIT ...,...

执行顺序

  1. FROM---> ON 多表的连接条件,可以过滤部分数据 ---(LEFT/RIGHT JOIN)
  2. WHERE (不可以使用别名)
  3. GROUP BY
  4. HAVING (可以使用别名)
  5. SELECT 的字段
  6. DISTINCT
  7. ORDER BY
  8. LIMIT

注意:SQL对查询做了增强没有严格遵循SQL的执行顺序,where后面不能用select中的别名,但是group by ,order by都是可以的racle数据库严格遵循了SQL执行顺序在Oracle里group by是不能引用select里的别名的

单行函数

对一行进行变换,每行返回一个结果

流程控制语句

函数 用法
IF(value,value1,value2) 如果value的值为TRUE,返回value1,否则返回value2
CASE WHEN 条件1 THEN 结果1 WHEN 条件2 THEN 结果2.... ELSE END 相当于Java的if...else if...else...
CASE expr WHEN 常量值1 THEN 值1 WHEN 常量值1 THEN值1 .... ELSE 值n END 相当于Java的switch...case...
SELECT IF(age>=25,'25岁及以上','25岁以下') AS age_cut,count(*)
FROM user_profile
group by age_cut;

/*
25岁及以上|4
25岁以下|3
*/

SELECT device_id, gender,CASE 
WHEN age IS NULL THEN '其他' 
WHEN age>=25 THEN '25岁及以上'
WHEN age>=20 THEN'20-24岁'
ELSE '20岁以下'
END  AS age_cut 
FROM user_profile
GROUP BY age_cut,gender,device_id

/*
2138|male|20-24岁
3214|male|其他
6543|female|20-24岁
2315|female|20-24岁
5432|male|25岁及以上
2131|male|25岁及以上
4321|male|25岁及以上
*/

SELECT CASE 1
WHEN 1 THEN '我是1'
WHEN 2 THEN '我是2'
ELSE '你是谁

日期函数

文本函数

MySQL中字符串的位置从1开始

函数 说明
LTRIM(s) 去掉字符串s左侧的空格
RTRIM(s) 去掉字符串s右侧的空格
TRIM(s) 去掉字符串s开始与结尾的空格
TRIM(s1 FROM s) 去掉字符串s开始与结尾的s1
TRIM(LEADING s1 FROM s) 去掉字符串s开始处的s1
TRIM(TRAILING s1FROM s) 去掉字符串s结尾处的s1
REPEAT(str, n) 返回str重复n次的结果
SUBSTRING_INDEX(str,delim,count) str:要处理的字符串,delim:分隔符,count:计数。
如果count是正数,那么就是从左往右数,第N个分隔符的左边的所有内容,如果count是负数,那么就是从右往左数,第N个分隔符的右边的所有内容
SUBSTRING(str,n ,m) 返回字符串str从第n个字符截取到第m个字符;

案例1:从180cm,75kg,25,male中提取出年龄25

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(profile,',',-2),',',1) AS age # 先截取出25,male再截取出25

数学函数

函数 说明
ROUND(x) 四舍五入,相当与ROUND(X,0)
ROUND(x,y) 四舍五入,并保留到小数点后面Y位
posted @ 2022-01-13 17:09  rananie  阅读(153)  评论(0编辑  收藏  举报