MySQL WHERE子句完全指南:精准过滤数据的艺术

一、WHERE子句语法格式详解

1.1 基础语法结构

WHERE子句是SELECT语句中的筛选条件部分,用于从表中提取满足特定条件的记录。

bash 复制代码
sql
SELECT 列名1, 列名2, ...
FROM 表名
WHERE 条件表达式;

1.2 完整的SELECT语句结构

bash 复制代码
sql
SELECT 
    [ALL | DISTINCT | DISTINCTROW] 
    select_expr [, select_expr ...]
FROM 
    table_references
[WHERE where_condition]        -- WHERE子句位置
[GROUP BY {col_name | expr | position}]
[HAVING where_condition]
[ORDER BY {col_name | expr | position} [ASC | DESC]]
[LIMIT {[offset,] row_count | row_count OFFSET offset}];

1.3 运算符优先级表

bash 复制代码
优先级	运算符	描述
1	=, <>, !=, <, <=, >, >=	比较运算符
2	BETWEEN, LIKE, IN, IS NULL	特殊比较
3	NOT	逻辑非
4	AND	逻辑与
5	OR	逻辑或

二、带IN关键字的查询:多值匹配

2.1 基本语法格式

bash 复制代码
sql
SELECT 列名 FROM 表名 
WHERE 列名 IN (值1, 值2, 值3, ...);

2.2 实际应用示例

bash 复制代码
sql
-- 示例表:员工表(employees)
CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    department VARCHAR(30),
    salary DECIMAL(10,2),
    hire_date DATE
);

-- 插入示例数据
INSERT INTO employees VALUES
(1, '张三', '技术部', 8500, '2022-03-15'),
(2, '李四', '销售部', 7500, '2021-08-22'),
(3, '王五', '技术部', 9200, '2020-11-05'),
(4, '赵六', '市场部', 6800, '2023-01-30'),
(5, '孙七', '人事部', 6500, '2022-06-18'),
(6, '周八', '技术部', 8800, '2021-09-10');
示例1:查询指定部门的员工
sql
-- 查询属于技术部或销售部的员工
SELECT 
    id AS '员工编号',
    name AS '姓名',
    department AS '部门',
    salary AS '薪资'
FROM employees
WHERE department IN ('技术部', '销售部');
查询结果:

text
员工编号  姓名   部门    薪资
1        张三   技术部  8500.00
2        李四   销售部  7500.00
3        王五   技术部  9200.00
6        周八   技术部  8800.00
bash 复制代码
示例2:IN子查询的运用
sql
-- 查询薪资高于平均薪资的员工
SELECT 
    name AS '姓名',
    salary AS '薪资'
FROM employees
WHERE salary IN (
    SELECT salary 
    FROM employees 
    WHERE salary > (SELECT AVG(salary) FROM employees)
);

2.3 NOT IN的用法

bash 复制代码
sql
-- 查询不在某些部门的员工
SELECT 
    name AS '姓名',
    department AS '部门'
FROM employees
WHERE department NOT IN ('人事部', '市场部');

三、带BETWEEN AND的范围查询

3.1 基础语法格式

bash 复制代码
sql
SELECT 列名 FROM 表名 
WHERE 列名 BETWEEN 值1 AND 值2;
-- 等价于:WHERE 列名 >= 值1 AND 列名 <= 值2

3.2 实际应用示例

bash 复制代码
sql
-- 示例表:学生成绩表(scores)
CREATE TABLE scores (
    student_id INT,
    student_name VARCHAR(50),
    subject VARCHAR(20),
    score INT,
    exam_date DATE
);

INSERT INTO scores VALUES
(101, '张三', '数学', 85, '2023-06-15'),
(102, '李四', '数学', 92, '2023-06-15'),
(103, '王五', '数学', 78, '2023-06-15'),
(104, '赵六', '数学', 65, '2023-06-15'),
(105, '孙七', '数学', 88, '2023-06-15');
示例1:查询分数在某个区间的学生
sql
-- 查询数学成绩在80-90分之间的学生
SELECT 
    student_id AS '学号',
    student_name AS '姓名',
    score AS '数学成绩'
FROM scores
WHERE subject = '数学' 
  AND score BETWEEN 80 AND 90;
查询结果:

text
学号  姓名  数学成绩
101   张三     85
105   孙七     88
示例2:日期范围查询
sql
-- 查询2023年上半年入职的员工
SELECT 
    name AS '姓名',
    department AS '部门',
    hire_date AS '入职日期'
FROM employees
WHERE hire_date BETWEEN '2023-01-01' AND '2023-06-30';
示例3:NOT BETWEEN的用法
sql
-- 查询薪资不在8000-9000范围内的员工
SELECT 
    name AS '姓名',
    salary AS '薪资'
FROM employees
WHERE salary NOT BETWEEN 8000 AND 9000;

3.3 注意事项

bash 复制代码
sql
-- BETWEEN包含边界值
WHERE score BETWEEN 80 AND 90  -- 包含80和90

-- 对于日期,注意时间部分
WHERE date_column BETWEEN '2023-01-01' AND '2023-01-31'
-- 等价于:'2023-01-01 00:00:00' 到 '2023-01-31 23:59:59'

四、带LIKE关键字的模糊查询

4.1 通配符说明

bash 复制代码
通配符	描述	示例
%	匹配任意多个字符(0个或多个)	张% 匹配"张三"、"张"
_	匹配单个字符	_三 匹配"张三"、"李三"
[charlist]	匹配字符列表中的任意一个	[张李]三 匹配"张三"、"李三"
[^charlist]	匹配不在字符列表中的任意一个	[^张李]三 匹配"王三"、"赵三"

4.2 实际应用示例

bash 复制代码
sql
-- 示例表:图书表(books)
CREATE TABLE books (
    book_id INT,
    book_name VARCHAR(100),
    author VARCHAR(50),
    price DECIMAL(8,2),
    publish_date DATE
);

INSERT INTO books VALUES
(1, 'MySQL数据库实战', '张三', 59.80, '2023-01-15'),
(2, 'Python编程从入门到精通', '李四', 79.90, '2022-11-20'),
(3, 'Java核心技术', '王五', 89.90, '2023-03-10'),
(4, 'Web前端开发实战', '李四', 69.90, '2022-09-05'),
(5, 'MySQL优化指南', '赵六', 49.90, '2023-05-20');
示例1:%通配符使用
sql
-- 查询书名包含"MySQL"的图书
SELECT 
    book_name AS '书名',
    author AS '作者',
    price AS '价格'
FROM books
WHERE book_name LIKE '%MySQL%';

-- 查询以"实战"结尾的图书
SELECT book_name 
FROM books 
WHERE book_name LIKE '%实战';

-- 查询以"Python"开头的图书
SELECT book_name 
FROM books 
WHERE book_name LIKE 'Python%';
示例2:_通配符使用
sql
-- 查询作者姓"李"且名字为两个字的图书
SELECT 
    book_name AS '书名',
    author AS '作者'
FROM books
WHERE author LIKE '李_';

-- 查询书名第三个字是"编"的图书
SELECT book_name 
FROM books 
WHERE book_name LIKE '__编%';
示例3:组合使用通配符
sql
-- 查询书名以"实战"结尾且长度至少为4个字的图书
SELECT book_name 
FROM books 
WHERE book_name LIKE '%实战' 
  AND LENGTH(book_name) >= 4;

-- 查询作者不是"张"、"李"、"王"开头的图书
SELECT book_name, author
FROM books
WHERE author NOT LIKE '[张李王]%';
示例4:ESCAPE转义字符
sql
-- 当需要查询包含%或_本身时
SELECT column_name 
FROM table_name 
WHERE column_name LIKE '%\%%' ESCAPE '\';  -- 查找包含%的内容

SELECT column_name 
FROM table_name 
WHERE column_name LIKE '%\_%' ESCAPE '\';  -- 查找包含_的内容

五、用IS NULL关键字查询空值

5.1 NULL值特性说明

NULL表示"未知"或"不存在"

NULL与任何值比较都返回NULL(包括NULL本身)

不能使用 = NULL 判断,必须使用 IS NULL

5.2 实际应用示例

bash 复制代码
sql
-- 示例表:客户表(customers)
CREATE TABLE customers (
    customer_id INT,
    customer_name VARCHAR(50),
    phone VARCHAR(20),
    email VARCHAR(100),
    address VARCHAR(200),
    register_date DATE
);

INSERT INTO customers VALUES
(1, '张三', '13800138001', 'zhangsan@email.com', '北京市朝阳区', '2023-01-15'),
(2, '李四', NULL, 'lisi@email.com', NULL, '2023-02-20'),
(3, '王五', '13900139002', NULL, '上海市浦东新区', '2023-03-10'),
(4, '赵六', NULL, NULL, NULL, '2023-04-05'),
(5, '孙七', '13700137003', 'sunqi@email.com', '广州市天河区', '2023-05-12');
示例1:查询空值
sql
-- 查询没有电话号码的客户
SELECT 
    customer_name AS '客户姓名',
    phone AS '联系电话',
    email AS '电子邮箱'
FROM customers
WHERE phone IS NULL;
查询结果:

text
客户姓名  联系电话  电子邮箱
李四      NULL     lisi@email.com
赵六      NULL     NULL
示例2:查询非空值
sql
-- 查询有电子邮箱的客户
SELECT 
    customer_name AS '客户姓名',
    email AS '电子邮箱'
FROM customers
WHERE email IS NOT NULL;
示例3:多列空值判断
sql
-- 查询既没有电话也没有地址的客户
SELECT 
    customer_name AS '客户姓名',
    register_date AS '注册日期'
FROM customers
WHERE phone IS NULL 
  AND address IS NULL;

5.3 空值处理函数

bash 复制代码
sql
-- 使用IFNULL处理空值显示
SELECT 
    customer_name AS '姓名',
    IFNULL(phone, '未登记') AS '联系电话',
    IFNULL(address, '地址不详') AS '联系地址'
FROM customers;

-- 使用COALESCE返回第一个非空值
SELECT 
    customer_name,
    COALESCE(email, phone, address, '无联系方式') AS '主要联系方式'
FROM customers;

六、带AND的多条件查询

6.1 基础语法格式

bash 复制代码
sql
SELECT 列名 FROM 表名 
WHERE 条件1 AND 条件2 AND 条件3 ...;

6.2 实际应用示例

bash 复制代码
sql
-- 示例表:订单表(orders)
CREATE TABLE orders (
    order_id INT,
    customer_id INT,
    product_name VARCHAR(100),
    quantity INT,
    unit_price DECIMAL(10,2),
    order_date DATE,
    status VARCHAR(20)
);

INSERT INTO orders VALUES
(1001, 1, '笔记本电脑', 1, 6999.00, '2023-10-15', '已完成'),
(1002, 2, '智能手机', 2, 2999.00, '2023-10-16', '待发货'),
(1003, 1, '平板电脑', 1, 3999.00, '2023-10-17', '已取消'),
(1004, 3, '无线耳机', 3, 399.00, '2023-10-18', '已完成'),
(1005, 2, '智能手表', 1, 1299.00, '2023-10-19', '待付款'),
(1006, 4, '显示器', 2, 1599.00, '2023-10-20', '待发货');
示例1:多条件组合查询
sql
-- 查询2023年10月订单金额超过5000元且状态为"已完成"的订单
SELECT 
    order_id AS '订单编号',
    product_name AS '产品名称',
    quantity AS '数量',
    unit_price AS '单价',
    (quantity * unit_price) AS '总金额',
    order_date AS '订单日期',
    status AS '订单状态'
FROM orders
WHERE order_date BETWEEN '2023-10-01' AND '2023-10-31'
  AND (quantity * unit_price) > 5000
  AND status = '已完成';
查询结果:

text
订单编号  产品名称    数量  单价      总金额    订单日期    订单状态
1001      笔记本电脑   1    6999.00   6999.00   2023-10-15  已完成
示例2:复杂条件组合
sql
-- 查询数量大于1且单价在1000-5000元之间的订单
SELECT 
    order_id,
    product_name,
    quantity,
    unit_price,
    status
FROM orders
WHERE quantity > 1 
  AND unit_price BETWEEN 1000 AND 5000
  AND status IN ('待发货', '已完成');
示例3:结合LIKE和AND
sql
-- 查询产品名称包含"电脑"且状态不是"已取消"的订单
SELECT 
    order_id AS '订单号',
    product_name AS '产品',
    status AS '状态'
FROM orders
WHERE product_name LIKE '%电脑%'
  AND status != '已取消';

6.3 注意事项

bash 复制代码
sql
-- 条件执行的优先级
WHERE 条件1 OR 条件2 AND 条件3
-- 等价于:WHERE 条件1 OR (条件2 AND 条件3)

-- 建议使用括号明确优先级
WHERE (条件1 OR 条件2) AND 条件3

七、带OR的多条件查询

7.1 基础语法格式

bash 复制代码
sql
SELECT 列名 FROM 表名 
WHERE 条件1 OR 条件2 OR 条件3 ...;

7.2 实际应用示例

bash 复制代码
sql
-- 示例表:员工考勤表(attendance)
CREATE TABLE attendance (
    record_id INT,
    employee_id INT,
    employee_name VARCHAR(50),
    department VARCHAR(30),
    attendance_date DATE,
    status VARCHAR(20)
);

INSERT INTO attendance VALUES
(1, 101, '张三', '技术部', '2023-10-23', '正常'),
(2, 102, '李四', '销售部', '2023-10-23', '迟到'),
(3, 103, '王五', '技术部', '2023-10-23', '请假'),
(4, 104, '赵六', '市场部', '2023-10-23', '正常'),
(5, 105, '孙七', '人事部', '2023-10-23', '早退'),
(6, 101, '张三', '技术部', '2023-10-24', '请假'),
(7, 102, '李四', '销售部', '2023-10-24', '正常');
示例1:简单OR条件查询
sql
-- 查询状态为"请假"或"迟到"的员工
SELECT 
    attendance_date AS '考勤日期',
    employee_name AS '员工姓名',
    department AS '部门',
    status AS '考勤状态'
FROM attendance
WHERE status = '请假' OR status = '迟到';
查询结果:

text
考勤日期   员工姓名  部门    考勤状态
2023-10-23  李四    销售部    迟到
2023-10-23  王五    技术部    请假
2023-10-24  张三    技术部    请假
示例2:OR与IN的等价转换
sql
-- 以下两种写法等价:
SELECT * FROM attendance 
WHERE status = '请假' OR status = '迟到' OR status = '早退';

SELECT * FROM attendance 
WHERE status IN ('请假', '迟到', '早退');
示例3:多列OR条件查询
sql
-- 查询部门为"技术部"或状态为"正常"的记录
SELECT 
    attendance_date AS '日期',
    employee_name AS '姓名',
    department AS '部门',
    status AS '状态'
FROM attendance
WHERE department = '技术部' OR status = '正常';

7.3 AND与OR的组合使用

bash 复制代码
示例1:复杂条件组合
sql
-- 查询(技术部且请假)或(销售部且迟到)的员工
SELECT 
    employee_name AS '姓名',
    department AS '部门',
    status AS '状态',
    attendance_date AS '日期'
FROM attendance
WHERE (department = '技术部' AND status = '请假')
   OR (department = '销售部' AND status = '迟到');
示例2:多层条件嵌套
sql
-- 查询(状态为正常)或(部门为技术部且状态不为早退)的记录
SELECT *
FROM attendance
WHERE status = '正常'
   OR (department = '技术部' AND status != '早退');

7.4 性能优化建议

bash 复制代码
sql
-- 不推荐的写法(OR导致索引失效)
SELECT * FROM orders 
WHERE customer_id = 1 OR product_name LIKE '%电脑%';

-- 推荐的改写方式(使用UNION)
SELECT * FROM orders WHERE customer_id = 1
UNION
SELECT * FROM orders WHERE product_name LIKE '%电脑%';

八、综合实战案例

8.1 复杂查询综合应用

bash 复制代码
sql
-- 创建一个综合示例表
CREATE TABLE sales (
    sale_id INT PRIMARY KEY,
    product_id INT,
    product_name VARCHAR(100),
    category VARCHAR(50),
    sale_date DATE,
    quantity INT,
    unit_price DECIMAL(10,2),
    salesperson VARCHAR(50),
    region VARCHAR(50)
);

-- 综合查询示例
SELECT 
    product_name AS '产品名称',
    category AS '产品类别',
    SUM(quantity) AS '总销量',
    SUM(quantity * unit_price) AS '总销售额',
    AVG(unit_price) AS '平均单价'
FROM sales
WHERE sale_date BETWEEN '2023-01-01' AND '2023-12-31'
  AND category IN ('电子产品', '办公用品')
  AND (region = '华东' OR region = '华南')
  AND quantity > 0
  AND salesperson IS NOT NULL
GROUP BY product_name, category
HAVING SUM(quantity * unit_price) > 10000
ORDER BY SUM(quantity * unit_price) DESC;

8.2 查询优化技巧总结

相关推荐
zzb15804 小时前
RAG from Scratch-优化-query
java·数据库·人工智能·后端·spring·mybatis
一只鹿鹿鹿4 小时前
信息安全等级保护安全建设防护解决方案(总体资料)
运维·开发语言·数据库·面试·职场和发展
堕2744 小时前
MySQL数据库《基础篇--数据库索引(2)》
数据库·mysql
wei_shuo4 小时前
数据库优化器进化论:金仓如何用智能下推把查询时间从秒级打到毫秒级
数据库·kingbase·金仓
71-35 小时前
MySQL的安装和卸载组件
笔记·学习·mysql
雷工笔记5 小时前
Navicat Premium 17 软件安装记录
数据库
wenlonglanying5 小时前
Ubuntu 系统下安装 Nginx
数据库·nginx·ubuntu
数据库小组5 小时前
10 分钟搞定!Docker 一键部署 NineData 社区版
数据库·docker·容器·database·数据库管理工具·ninedata·迁移工具
爬山算法6 小时前
MongoDB(38)如何使用聚合进行投影?
数据库·mongodb
l1t6 小时前
Deep Seek总结的APSW 和 SQLite 的关系
数据库·sqlite