云计算百科
云计算领域专业知识百科平台

零基础学SQL 04:SQL 的 WHERE 越写越乱?AND/OR 优先级、IN、BETWEEN、LIKE 一次讲透(附 3 个新手坑)

先说点真话

当年做数据分析项目那会儿,有回要给领导出一张"技术部 + 销售部里,工资超过 9000 的人"的名单。新人交上来的 SQL 长这样:

WHERE 部门='技术部' OR 部门='销售部' AND 工资>9000

结果查出来技术部所有人(含工资 8000 的)全在里头——因为 AND 优先级高于 OR,上面那句实际等于"技术部全部,或者(销售部且工资>9000)"。上报的数字直接错了,挨了一顿批。

这事儿让我记住:WHERE 不只会写单个条件,条件一多,优先级和写法就是坑。今天把 AND/OR、IN、BETWEEN、LIKE 一次讲透,你写报表、做筛选再也不会被自己坑。

💡 「SQL 从入门到精通」系列持续更新中,关注我不迷路,每篇都是实战干货。


一、AND / OR:多条件组合,先搞清优先级

你会什么场景下用到它? 你想同时卡好几个条件,比如"技术部且工资>9000"“北京或上海的客户”。这时候就要用 AND(并且)和 OR(或者)把条件拼起来。

关键点:AND 比 OR 优先级高。 就像乘法比加法先算一样。想改变顺序,必须加括号 ()。

正确写法(加括号才是你真正想要的):

— 意图:只要"技术部或销售部"里,工资>9000 的人
SELECT 姓名, 部门, 工资
FROM 员工表
WHERE (部门='技术部' OR 部门='销售部') AND 工资 > 9000;

结果(技术部 9000 不达标被排除,销售部 9200 两人达标):

姓名部门工资
王五 销售部 9200
赵六 销售部 9200

最大的坑: 不加括号时,数据库按"先 AND 后 OR"算。下面这句和上面那句意思完全不同:

— ❌ 实际含义:技术部全部,或(销售部且工资>9000)
WHERE 部门='技术部' OR 部门='销售部' AND 工资 > 9000

记住口诀:条件一多,先想清楚"我要的是哪一组",然后用括号把那组括起来。宁可多写括号,别信默认优先级。


二、IN:替代一长串 OR,清爽又高效

你会什么场景下用到它? 你想筛"部门是技术部或销售部或市场部",用 OR 要写三遍 部门=,又长又难看:

— 啰嗦写法
WHERE 部门='技术部' OR 部门='销售部' OR 部门='市场部'

正确写法:用 IN 一把梭

SELECT 姓名, 部门
FROM 员工表
WHERE 部门 IN ('技术部', '销售部', '市场部');

IN 后面跟一个值列表,等于"等于其中任意一个"。可读性高,数据库也更容易优化。你后面学子查询时,IN (SELECT …) 还能接一整张结果表,非常常用。


三、BETWEEN:闭区间范围筛选

你会什么场景下用到它? 你想筛"工资在 8000 到 9500 之间",包括 8000 和 9500 两端。

正确写法:

SELECT 姓名, 工资
FROM 员工表
WHERE 工资 BETWEEN 8000 AND 9500;

两个要点:

  • BETWEEN 是闭区间,包含两端(8000 和 9500 都算)。
  • 等价于 工资 >= 8000 AND 工资 <= 9500,但 BETWEEN 写起来更短,语义更清楚。

我当年踩的坑: 有人以为 BETWEEN 不含边界,少算了临界值,报表差了那么几个人。所以记住——BETWEEN 两头都算。


四、LIKE:模糊查询,找"长得像"的数据

你会什么场景下用到它? 你记不全准确名字,只想找"姓张的"“名字里带’小’的”“邮箱是 demo 结尾的”。精确等号 = 匹配不了,就要用 LIKE 做模糊匹配。

两个通配符:

  • %:代表任意长度(0 个、1 个、多个字符)
  • _:代表恰好 1 个字符

正确写法:

— 姓"张"的(张开头,后面任意)
SELECT 姓名 FROM 员工表 WHERE 姓名 LIKE '张%';

— 名字里带"小"的(小在任意位置)
SELECT 姓名 FROM 用户表 WHERE 姓名 LIKE '%小%';

— 邮箱是 demo.com 结尾的
SELECT 邮箱 FROM 用户表 WHERE 邮箱 LIKE '%demo.com';

— 姓名恰好 2 个字、且姓张(_ 占一个位置)
SELECT 姓名 FROM 员工表 WHERE 姓名 LIKE '张_';

我当年踩的坑(性能): 在一张几千万行的大表里写 LIKE '%关键字%'(前面带 %),数据库没法用索引,只能全表逐行扫,查询直接超时。结论:LIKE 的通配符放前面(前导通配)会拖慢查询,大表能避免就避免,非要搜就尽量写成 '关键字%'(后缀匹配,能用索引)。


五、当年我踩过的 3 个坑(重点看)

  • AND/OR 不加括号,统计口径错 上面那个"技术部或销售部且>9000"的例子,少一对括号,上报数字全错。结论:多条件必加括号,别赌默认优先级。

  • 以为 BETWEEN 不含边界 漏算临界值,报表人数差几个。结论:BETWEEN 闭区间,两头都算。

  • LIKE 前导通配符拖垮大表查询 '%x%' 让几千万行表全表扫描、查询超时。结论:模糊查询尽量写成 'x%',别在前面加 %。


  • 六、3 个练习(自己跑一遍)

    基于下面的 员工表 和 订单表:

  • 查出工资在 9000 到 9500 之间的员工姓名和工资。
  • 查出部门是技术部或销售部,且工资大于 9000 的员工。
  • 用 LIKE 查出姓名以"王"开头的员工。
  • 参考答案(先自己写,再对照):

    — 1
    SELECT 姓名, 工资 FROM 员工表 WHERE 工资 BETWEEN 9000 AND 9500;

    — 2(括号决定优先级)
    SELECT 姓名, 部门, 工资
    FROM 员工表
    WHERE (部门='技术部' OR 部门='销售部') AND 工资 > 9000;

    — 3
    SELECT 姓名 FROM 员工表 WHERE 姓名 LIKE '王%';

    思考题:练习 2 如果不加括号,结果会变成什么?为什么技术部工资 9000 的人会被算进来?想明白这个,AND/OR 优先级这关就过了。


    七、小结

    • AND(并且)/ OR(或者)组合条件,AND 优先级高于 OR,多条件必加括号。
    • IN (值1, 值2, …) 替代一长串 OR,清爽高效,后面还能接子查询。
    • BETWEEN A AND B 是闭区间,包含 A 和 B 两端。
    • LIKE 模糊匹配:% 任意长度、_ 恰好一个;前导通配 %x% 会拖慢大表查询,尽量写成 x%。

    互动时间(站队投票):你写 WHERE 时最常被哪块坑过?我当年铁定选"AND/OR 不加括号,然后对着错数字发呆"。是 ① AND/OR 优先级、② BETWEEN 边界、还是 ③ LIKE 慢查询?评论区打 1/2/3,我挑典型的下篇专门讲索引优化避坑 😂

    👋 我是 Hello_world12131,十年数据分析经验。 这篇有用的话 点个赞 + 收藏,顺便 关注我 📌,SQL 从入门到精通系列每周更新,关注后不错过新篇。 📎 系列目录(置顶) | 🔗 相关推荐: 篇02 SELECT/FROM/WHERE 篇03 ORDER BY/GROUP BY/HAVING SQL 函数速查表 | ⏭️ 下篇预告:篇05 去重与分页 DISTINCT/LIMIT


    📋 SQL 系列统一练习表(复制即可运行,可重复执行,不会报"表已存在")

    本系列所有文章都基于下面这 4 张固定表。每张表先 DROP 再 CREATE,所以每读一篇文重新跑一次这个块都安全,不用从新建表。

    DROP TABLE IF EXISTS 员工表;
    CREATE TABLE 员工表 (
    员工id INT PRIMARY KEY,
    姓名 VARCHAR(20),
    部门 VARCHAR(20),
    工资 DECIMAL(10,2),
    邮箱 VARCHAR(50),
    手机 VARCHAR(20),
    入职日期 DATE
    );
    INSERT INTO 员工表 (员工id, 姓名, 部门, 工资, 邮箱, 手机, 入职日期) VALUES
    (1, '张三', '技术部', 9000.00, 'zhangsan@demo.com', '13800000001', '2019-03-01'),
    (2, '李四', '技术部', 9000.00, 'lisi@demo.com', '13800000002', '2020-07-15'),
    (3, '王五', '销售部', 9200.00, 'wangwu@demo.com', '13800000003', '2018-01-10'),
    (4, '赵六', '销售部', 9200.00, 'zhaoliu@demo.com', '13800000004', '2021-05-20');

    DROP TABLE IF EXISTS 订单表;
    CREATE TABLE 订单表 (
    订单id INT PRIMARY KEY,
    员工id INT,
    订单金额 DECIMAL(10,2),
    下单时间 DATETIME,
    付款时间 DATETIME,
    状态 VARCHAR(20)
    );
    INSERT INTO 订单表 (订单id, 员工id, 订单金额, 下单时间, 付款时间, 状态) VALUES
    (101, 1, 3000.00, '2026-01-10 10:00:00', '2026-01-10 10:05:00', '已付款'),
    (102, 1, 2500.00, '2026-02-15 14:00:00', '2026-02-15 14:10:00', '已付款'),
    (103, 3, 4000.00, '2026-03-20 09:30:00', '2026-03-20 09:40:00', '已付款'),
    (104, 2, 1500.00, '2026-04-05 16:00:00', NULL, '待付款');

    DROP TABLE IF EXISTS 用户表;
    CREATE TABLE 用户表 (
    用户id INT PRIMARY KEY,
    姓名 VARCHAR(20),
    手机 VARCHAR(20),
    邮箱 VARCHAR(50),
    地址 VARCHAR(100)
    );
    INSERT INTO 用户表 (用户id, 姓名, 手机, 邮箱, 地址) VALUES
    (1, '张三', '13900000001', 'zhangsan@demo.com', '北京市朝阳区'),
    (2, '李四', '13900000002', 'lisi@demo.com', '上海市浦东新区'),
    (3, '王五', '13900000003', 'wangwu@demo.com', '广州市天河区');

    DROP TABLE IF EXISTS 任务表;
    CREATE TABLE 任务表 (
    任务id INT PRIMARY KEY,
    员工id INT,
    备注 VARCHAR(100),
    状态 VARCHAR(20)
    );
    INSERT INTO 任务表 (任务id, 员工id, 备注, 状态) VALUES
    (1, 1, '完成需求评审', '已完成'),
    (2, 2, NULL, '进行中'),
    (3, 3, '修复线上bug', '已完成'),
    (4, 4, NULL, '待分配');

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 零基础学SQL 04:SQL 的 WHERE 越写越乱?AND/OR 优先级、IN、BETWEEN、LIKE 一次讲透(附 3 个新手坑)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!