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 查询优化技巧总结

相关推荐
大鳥2 小时前
第一章 - 数据仓库是什么
大数据·数据库·hive
u0109272714 小时前
RESTful API设计最佳实践(Python版)
jvm·数据库·python
qq_1927798710 小时前
高级爬虫技巧:处理JavaScript渲染(Selenium)
jvm·数据库·python
u01092727111 小时前
使用Plotly创建交互式图表
jvm·数据库·python
爱学习的阿磊11 小时前
Python GUI开发:Tkinter入门教程
jvm·数据库·python
tudficdew11 小时前
实战:用Python分析某电商销售数据
jvm·数据库·python
Fleshy数模12 小时前
CentOS7 安装配置 MySQL5.7 完整教程(本地虚拟机学习版)
linux·mysql·centos
sjjhd65212 小时前
Python日志记录(Logging)最佳实践
jvm·数据库·python
Configure-Handler12 小时前
buildroot System configuration
java·服务器·数据库