做了很多年数据查询和报表开发,我越来越觉得SQL里最值得反复练的就是WHERE、ORDER BY、GROUP BY这三兄弟。表面上看它们只是几个单词,但实际业务里绝大多数的取数需求,拆到底层都是“先圈范围、再定顺序、后做汇总”这个套路。今天我就拿一套真实的订单明细数据,把这三个核心查询语法从头到尾串起来讲一遍,从原理到实操、从踩坑到优化,尽量让刚接触数据库的同学也能照着写出可用的查询语句。
这篇文章适合谁看?两类人最合适:一类是刚学完SQL基础语法、准备做数据分析或后端开发的小白,另一类是日常用Excel处理数据、想转成SQL提数的业务同学。内容不需要你有多深的计算机背景,只要会认几个常用的英文单词就能跟上。看完之后,你至少能弄明白三个问题:WHERE和HAVING到底什么时候用哪个?ORDER BY多字段排序为什么顺序不能乱?GROUP BY分组后怎么过滤结果才不出错?
1. 写查询前必须理解的底层逻辑
1.1 我需要一张什么样的测试表
为了不讲空话,我先定义一张订单明细表,后续所有示例都基于这张表来跑。表名叫sales_order,每条记录是一笔订单,字段分别有订单号、下单日期、客户编号、所属区域、产品名称、产品分类、销售数量、成交金额和销售负责人。
sql复制CREATE TABLE sales_order (
order_id VARCHAR(10),
order_date DATE,
customer_id VARCHAR(10),
region VARCHAR(20),
product_name VARCHAR(50),
category VARCHAR(20),
quantity INT,
amount DECIMAL(10,2),
salesperson VARCHAR(20)
);
我往里面塞了几行比较有代表性的数据,覆盖了不同区域、不同月份、不同产品和不同负责人。后面但凡要解释某个语法现象,你都可以在这个数据集上亲手跑一遍验证,而不是干看我写。
sql复制INSERT INTO sales_order VALUES
('A001', '2024-01-05', 'U1001', '华东', '手机', '数码', 2, 6000.00, '张三'),
('A002', '2024-01-12', 'U1002', '华东', '平板', '数码', 1, 4000.00, '李四'),
('A003', '2024-02-03', 'U1003', '华北', '手机', '数码', 3, 9000.00, '王五'),
('A004', '2024-02-18', 'U1004', '华北', '耳机', '配件', 5, 1250.00, '王五'),
('A005', '2024-03-02', 'U1005', '华南', '手机', '数码', 1, 3000.00, '张三'),
('A006', '2024-03-15', 'U1006', '华南', '支架', '配件', 10, 500.00, '李四'),
('A007', '2024-04-20', 'U1007', '华东', '平板', '数码', 2, 8000.00, '王五');
这张表一共7行,数据量不大,但足够把WHERE的过滤逻辑、ORDER BY的排序规则和GROUP BY的聚合行为都演示清楚。如果你本机有MySQL、PostgreSQL或者SQL Server,直接建表跑一遍效果最好。
1.2 为什么说执行顺序比书写顺序更关键
很多初学者都会背“SELECT要写在最前面”,但真正让一个查询跑起来的时候,数据库并不是从上到下执行的。完整的逻辑执行顺序大体是这样的:先确定数据来源(FROM),再过滤行(WHERE),然后按条件分组(GROUP BY),用HAVING过滤分组结果,接着才轮到SELECT投影列,最后做DISTINCT去重、ORDER BY排序和LIMIT限制返回行数。
这个顺序是理解三大语法协作关系的钥匙。我举个最典型的例子:你写WHERE amount > 1000和HAVING amount > 1000,表面看都是过滤,但在执行顺序里一个发生在分组前、一个发生在分组后,所以WHERE没法使用聚合函数,限制的是原始行,而HAVING配合聚合函数限制的是分组结果。不搞懂这个,写多表分组查询时经常会莫名其妙报错或者算错数。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. WHERE:先把无关数据行挡在门外
2.1 过滤条件的核心运算符与判断逻辑
WHERE的作用只有一个:从表里挑选出满足条件的行。它最常用的运算符包括比较运算符=、<>、>、<、>=、<=,逻辑运算符AND、OR、NOT,范围判断BETWEEN ... AND ...,集合判断IN (...),以及模糊匹配LIKE。写条件的时候,一定要把“条件表达式返回的是真还是假”记在脑子里。
比如我现在想看华东区域卖出的所有订单,最简单的写法是:
sql复制SELECT order_id, product_name, amount
FROM sales_order
WHERE region = '华东';
这个很好理解。但如果是多条件组合,就涉及到一个很多人栽过的坑:WHER子句里同时出现AND和OR的时候,AND的优先级高于OR。比如我想查“华东区域”的订单,或者“金额大于5000”的所有订单,并且还要产品销售负责人是王五,这个需求如果直接写成下面这样就会出问题:
sql复制WHERE region = '华东' OR amount > 5000 AND salesperson = '王五';
数据库会把
