MySQL 查询与函数详解:从基础条件筛选到高级字符处理

1. 引言

在数据库操作中,SQL(Structured Query Language)是进行数据查询、操作和管理的核心语言。无论是简单的数据检索还是复杂的数据分析,掌握 SQL 查询语句和内置函数的使用都至关重要。本文将以 MySQL 数据库为例,通过一系列实际案例,深入讲解条件查询、排序查询以及常用函数的使用方法,帮助读者从基础到进阶全面掌握 SQL 查询技巧。

2. 条件查询详解

条件查询是 SQL 中最基础也是最常用的操作之一,它允许我们根据特定条件从表中筛选出所需的数据。WHERE 子句是实现条件查询的关键,支持多种运算符和逻辑组合。

2.1 IN 运算符的使用

IN 运算符用于指定多个可能的值,比使用多个 OR 运算符更加简洁高效。其基本语法为:WHERE column_name IN (value1, value2, ...)

sql 复制代码
-- 示例:查询员工的工种编号是 IT_PROG、AD_VP、AD_PRES 中的一个员工名和工种编号
/* 分析:
   查询的表:employees
   查询的字段:first_name, job_id
   查询的条件:job_id in ('IT_PROG','AD_VP','AD_PRES')
   等价于:job_id = 'IT_PROG' OR job_id = 'AD_VP' OR job_id = 'AD_PRES'
*/
SELECT 
    first_name,
    job_id
FROM 
    employees
WHERE 
    job_id IN ('IT_PROG','AD_VP','AD_PRES');

使用 IN 运算符的优势:

  • 代码简洁:避免重复书写多个 OR 条件
  • 可读性强:逻辑表达更加清晰直观
  • 性能优化:在某些情况下,数据库优化器能更好地处理 IN 查询

2.2 NULL 值处理

NULL 在数据库中表示缺失或未知的值,处理 NULL 值需要特别注意,因为 NULL 与任何值的比较(包括 NULL 自身)都会返回 NULL,而不是 TRUE 或 FALSE。

sql 复制代码
-- 示例:查询没有奖金率的员工名和奖金率
/* 分析:
   查询的表:employees
   查询的字段:first_name, commission_pct
   查询的条件:commission_pct IS NULL
*/
SELECT 
    first_name,
    commission_pct
FROM 
    employees
WHERE 
    commission_pct IS NULL;

重要提醒:不能使用等号(=)判断 NULL 值。以下查询是错误的:

sql 复制代码
-- 错误示例:查询 salary 等于 12000 的员工
-- SELECT first_name, commission_pct
-- FROM employees
-- WHERE salary IS 12000;  -- 这是错误的语法!

2.3 安全等于运算符(<=>)

MySQL 提供了安全等于运算符 <=>,它可以同时处理 NULL 值和普通数值的比较。

sql 复制代码
-- 使用安全等于运算符查询没有奖金率的员工
SELECT 
    first_name,
    commission_pct
FROM 
    employees
WHERE 
    commission_pct <=> NULL;
-- 安全等于运算符也可以用于普通数值的比较
SELECT
*
FROM
employees
WHERE
salary <=> 12000;

IS NULL 与 <=> 对比

  • IS NULL:专门用于判断 NULL 值,可读性高,建议优先使用
  • <=>:既可以判断 NULL 值,又可以判断普通数值,但可读性较低

3. 排序查询(ORDER BY)

排序查询允许我们按照指定的列对结果集进行排序,这在数据展示和分析中非常有用。

3.1 排序查询基本语法

sql 复制代码
-- 排序查询总结语法格式:
SELECT 
   查询列表 (3)
FROM 
   表名 (1)
[WHERE 筛选条件] (2)
ORDER BY 排序列表 [ASC | DESC] (4)

语法说明:

  • ASC:代表升序(Ascending),从小到大排列
  • DESC:代表降序(Descending),从大到小排列
  • 如果不指定排序方向,默认使用 ASC(升序)
  • ORDER BY 子句支持单个字段、多个字段、表达式、函数、别名
  • ORDER BY 子句一般放在查询语句的最后面(LIMIT 子句除外)

3.2 基础排序示例

sql 复制代码
-- 示例:查询员工信息,要求工资从高到低排序
/* 分析:
   查询的表:employees
   查询的字段:*
   查询的条件:无
   排序条件:salary DESC
*/
SELECT 
    *
FROM 
    employees
ORDER BY salary DESC;
-- 默认升序排序(ASC 可以省略)
SELECT
*
FROM
employees
ORDER BY salary;

3.3 带筛选条件的排序

sql 复制代码
-- 示例:查询部门编号大于等于90的员工信息,按入职时间的先后顺序进行排序
/* 分析:
   查询的表:employees
   查询的字段:*
   查询的条件:department_id >= 90
   排序条件:hiredate ASC
*/
SELECT 
    *
FROM 
    employees
WHERE 
    department_id >= 90
ORDER BY 
    hiredate ASC;

3.4 按表达式排序

sql 复制代码
-- 示例:按年薪的高低显示员工的信息和年薪
/* 分析:
   查询的表:employees
   查询的字段:*, 年薪
   查询的条件:无
   排序条件:salary * 12 * (1 + commission_pct) DESC
*/
-- IFNULL(commission_pct,0):判断是否为空,如果为空补0
SELECT 
    *,
    salary * 12 * (1 + IFNULL(commission_pct,0)) AS 年薪
FROM 
    employees
ORDER BY 
    salary * 12 * (1 + IFNULL(commission_pct,0)) DESC;

3.5 按别名排序

sql 复制代码
-- 示例:按年薪的高低显示员工的信息和年薪(按别名排序)
SELECT 
    *,
    salary * 12 * (1 + IFNULL(commission_pct,0)) AS 年薪
FROM 
    employees
ORDER BY 
    年薪 DESC;

3.6 按函数排序

sql 复制代码
-- 示例:按姓名的长度显示员工的姓名和工资
/* 分析:
   查询的表:employees
   查询的字段:姓名长度, 姓名, 工资
   查询的条件:无
   排序条件:函数排序 DESC
*/
SELECT 
    LENGTH(CONCAT(last_name, first_name)) AS 姓名长度,
    CONCAT(last_name, first_name) AS 姓名,
    salary
FROM 
    employees
ORDER BY 
    LENGTH(CONCAT(last_name, first_name)) DESC;

3.7 多字段排序

sql 复制代码
-- 示例:查询员工信息,要求先按工资升序,再按员工编号降序
/* 分析:
   查询的表:employees
   查询的字段:*
   查询的条件:无
   排序条件:salary ASC, employee_id DESC
*/
SELECT 
    *
FROM 
    employees
ORDER BY 
    salary ASC, employee_id DESC;

4. MySQL 常见函数详解

函数是将一组逻辑语句封装在方法中,对外暴露方法名的工具。函数的好处在于隐藏了实现细节,提高了代码的重用性。

4.1 函数概述

函数调用语法格式SELECT 函数名(实参列表) [FROM 表名]

函数特点

  • 叫什么(函数名称)
  • 干什么(函数功能)

函数分类

  • 单行函数:字符函数、数值函数、日期函数、其他函数、流程控制函数
  • 分组函数(聚合函数):用于对一组值执行计算并返回单个值

4.2 字符函数

4.2.1 LENGTH(str) - 获取字节个数
sql 复制代码
-- 获取参数值的字节个数
SELECT LENGTH('hello');  -- 返回 5
-- 注意:对于非 ASCII 字符(如汉字),LENGTH 函数返回的不是字符的个数,而是字符串的字节数
SELECT LENGTH('你好hello');  -- 在 UTF-8 编码下,每个汉字占3个字节,返回 11(3+3+5)

查看 MySQL 默认编码格式

sql 复制代码
SHOW VARIABLES LIKE '%char%';
4.2.2 CONCAT() - 字符串连接
sql 复制代码
-- 返回连接后的字符串
SELECT CONCAT(last_name, first_name) FROM employees;
-- 连接常量字符串
SELECT CONCAT('2026', '-', '08', '-', '17');
4.2.3 CONCAT_WS() - 带分隔符的连接
sql 复制代码
-- 返回带分隔符的连接结果
SELECT CONCAT_WS('-', '2026', '08', '17');  -- 返回 '2026-08-17'
4.2.4 UPPER() 和 LOWER() - 大小写转换
sql 复制代码
-- UPPER(str):将字符串转换为大写
SELECT UPPER('hello');  -- 返回 'HELLO'
-- LOWER(str):将字符串转换为小写
SELECT LOWER('HELLO');  -- 返回 'hello'
-- 示例:将姓变为大写,名变为小写,然后拼接
SELECT
CONCAT(UPPER(last_name), LOWER(first_name)) AS name_concat
FROM
employees;
-- 使用 CONCAT_WS 添加分隔符
SELECT
CONCAT_WS('_', UPPER(last_name), LOWER(first_name)) AS name_concat
FROM
employees;
4.2.5 SUBSTR() / SUBSTRING() - 截取子字符串
sql 复制代码
-- SUBSTR(str,pos):从指定位置开始截取到字符串末尾
SELECT SUBSTR('欢迎来到兰智数加学院', 5) AS out_put;  -- 返回 '兰智数加学院'
-- SUBSTR(str,pos,len):从指定位置开始截取指定长度的子字符串
SELECT SUBSTR('欢迎来到兰智数加学院', 7, 2) AS out_put;  -- 返回 '数加'
SELECT SUBSTRING('欢迎来到兰智数加学院', 7, 2) AS out_put;  -- 返回 '数加'

参数说明

  • str:原始字符串
  • pos:子字符串的起始位置,从 1 开始计数
  • len:要截取的长度(可选)
sql 复制代码
-- 示例:姓名中的姓首字母大写,其他字符小写,然后使用_拼接
SELECT 
    CONCAT(UPPER(SUBSTR(last_name, 1, 1)), '_', LOWER(SUBSTR(last_name, 2))) AS out_put
FROM 
    employees;
4.2.6 INSTR() - 查找子字符串位置
sql 复制代码
-- 返回子字符串首次出现的索引位置
SELECT INSTR('欢迎来到兰智数加学院', '学院');  -- 返回子字符串的位置
-- 如果子字符串不在原始字符串中,则返回 0
SELECT INSTR('欢迎来到兰智数加学院', '数模');  -- 返回 0
-- 注意:参数是二进制字符串时才区分大小写
SELECT INSTR('欢hhhh迎来到HHHH兰智数加学院', 'H');  -- 返回位置
4.2.7 TRIM() 系列函数 - 去除空格
sql 复制代码
-- TRIM():删除前导空格和尾随空格
SELECT LENGTH(TRIM('   兰智数加学院       ')) AS out_put;  -- 返回去除空格后的长度
SELECT TRIM('   兰智数加学院       ') AS out_put;  -- 返回 '兰智数加学院'
-- RTRIM():删除尾随空格(右侧空格)
-- LTRIM():删除前导空格(左侧空格)

思考题:如何删除字符串中间的空格?例如 "兰智 数加 学院" 中间的空格。

4.2.8 LPAD() 和 RPAD() - 字符串填充
sql 复制代码
-- LPAD(str,len,padstr):在字符串左侧填充指定字符,使总长度达到指定值
SELECT LPAD('数加', 4, '*') AS output;  -- 返回 '**数加'
-- RPAD(str,len,padstr):在字符串右侧填充指定字符
SELECT RPAD('数加', 4, '*') AS output;  -- 返回 '数加**'

思考题:如何将 "马冬梅" 转换为 "马*梅"?

4.2.9 REPLACE() - 字符串替换
sql 复制代码
-- REPLACE(str,from_str,to_str):替换指定字符串的所有出现位置
SELECT REPLACE('欢迎来到兰智数加学院', '学院', '大学') AS out_put;  -- 返回 '欢迎来到兰智数加大学'

4.3 数学函数

4.3.1 ROUND() - 四舍五入
sql 复制代码
-- ROUND(X):将参数四舍五入到整数
SELECT ROUND(3.14);  -- 返回 3
-- ROUND(X,D):将参数四舍五入到 D 位小数
SELECT ROUND(3.1415926, 2) AS out_put;  -- 返回 3.14

5. 实战应用与最佳实践

5.1 综合查询示例

结合条件查询、排序和函数使用,我们可以构建更复杂的查询:

sql 复制代码
-- 示例:查询部门编号在 50-100 之间,按姓名长度降序排列,并显示格式化后的姓名
SELECT 
    employee_id,
    CONCAT(UPPER(SUBSTR(last_name, 1, 1)), LOWER(SUBSTR(last_name, 2)), 
           ' ', 
           UPPER(SUBSTR(first_name, 1, 1)), LOWER(SUBSTR(first_name, 2))) AS formatted_name,
    salary,
    department_id,
    LENGTH(CONCAT(last_name, first_name)) AS name_length
FROM 
    employees
WHERE 
    department_id BETWEEN 50 AND 100
    AND commission_pct IS NOT NULL
ORDER BY 
    name_length DESC,
    salary ASC;

5.2 性能优化建议

  • 合理使用索引:在 WHERE 和 ORDER BY 子句中频繁使用的列上创建索引
  • 避免在 WHERE 子句中对列进行函数操作:这会导致索引失效
  • 使用 EXPLAIN 分析查询计划:了解 MySQL 如何执行查询
  • 限制结果集大小:使用 LIMIT 子句避免返回过多数据

5.3 常见错误与解决方法

  1. NULL 值处理错误:始终使用 IS NULL 或 IS NOT NULL 判断 NULL 值
  2. 字符串函数编码问题:注意字符集对 LENGTH() 等函数的影响
  3. 排序性能问题:对大表排序时考虑添加合适的索引
  4. 函数嵌套过深:避免过度嵌套函数,影响可读性和性能

6. 总结

本文详细介绍了 MySQL 中条件查询、排序查询以及常用函数的使用方法,涵盖了从基础语法到实战应用的完整知识体系。

核心要点回顾:

  • 条件查询(WHERE):掌握 IN 运算符简化多值匹配,理解 NULL 值的特殊性并使用 IS NULL/IS NOT NULL 进行判断,了解安全等于运算符(<=>)的用法。
  • 排序查询(ORDER BY):支持按字段、表达式、函数、别名以及多字段组合排序,ASC(升序)和 DESC(降序)控制排序方向。
  • 常用函数:包括字符函数(LENGTH、CONCAT、SUBSTR、INSTR、TRIM、LPAD/RPAD、REPLACE 等)和数学函数(ROUND 等),这些函数能显著提升数据处理能力。
  • 实战应用:通过综合查询示例展示了如何将条件、排序和函数结合使用,构建复杂且高效的查询语句。
  • 最佳实践:合理使用索引、避免 WHERE 子句中的函数操作、使用 EXPLAIN 分析查询计划等优化技巧,以及常见错误的解决方法。

SQL 查询是数据库操作的核心技能,熟练掌握条件查询、排序和函数的使用,能够帮助开发者更高效地从数据库中提取、分析和展示所需数据。建议读者在实际项目中多加练习,结合具体业务场景灵活运用这些技巧,不断提升 SQL 查询能力。

相关推荐
奥莱维1 小时前
KNX酒店方案_KNX专用线与高端酒店技术逻辑
java·服务器·前端·数据库
牛大兵1 小时前
机顶盒获取局域网已经使用IP,开放的端口号,扫描摄像头,NAS,共享主机等开机自启局域网全量扫描工具
数据库·网络协议·tcp/ip
知行产研1 小时前
中国矿山无人驾驶出海的三重门
数据库·mysql·php
l1258652 小时前
# RAG低延迟架构设计:从5秒到500ms的优化全链路
数据库·人工智能·python·langchain
RisunJan2 小时前
Linux命令-vgdisplay(显示卷组详细属性)
linux·运维·数据库
爱和冰阔落2 小时前
【MySQL 慢查询排查实战】列表接口逐渐变慢时,怎样从请求链路定位原因
android·数据库·mysql
JacksonMx2 小时前
企业级 JPA 与数据库架构落地指南
数据库·数据库架构
Dxy12393102162 小时前
MySQL有哪些锁?InnoDB锁体系完整梳理博客
数据库·mysql
wear工程师3 小时前
MySQL 索引条件下推是什么?Using index condition 并不是覆盖索引
sql·mysql