一、核心基础语法(ES6+ 全支持)

语法类型 示例代码 说明
箭头函数 pm.test("测试名称", () => { ... }) 替代传统function,简洁(你截图中的写法✅)
变量声明 const res = pm.response.json(); const(常量)/let(变量),替代var
解构赋值 const { code, data } = res; 快速提取响应 JSON 中的字段
模板字符串 console.log(状态码:${pm.response.code}); 拼接字符串更优雅

二、高频测试场景语法

1. 响应状态码 / 格式校验

javascript

运行

// 箭头函数极简写法(单行)
pm.test("响应码为200", () => pm.response.to.have.status(200));
pm.test("响应为JSON格式", () => pm.response.to.be.json);

// 多行逻辑(箭头函数)
pm.test("响应码非500", () => {
  const status = pm.response.code;
  pm.expect(status).to.not.equal(500); // 断言语法
});

2. 响应 JSON 字段校验

javascript

运行

pm.test("校验返回数据", () => {
  const res = pm.response.json(); // 解析JSON响应
  // 基础断言
  pm.expect(res.code).to.equal(0); // 校验code为0
  pm.expect(res.data).to.not.be.empty; // 校验data非空
  pm.expect(res.msg).to.include("成功"); // 包含指定文本
  
  // 数组/对象校验(箭头函数遍历)
  res.data.list.forEach(item => {
    pm.expect(item.id).to.be.a("number"); // 类型校验
    pm.expect(item.name).to.not.be.null; // 非空校验
  });
});

3. 环境变量 / 全局变量操作

javascript

运行

pm.test("设置/获取变量", () => {
  // 设置变量(箭头函数简化赋值逻辑)
  const setToken = (token) => pm.environment.set("token", token);
  setToken(pm.response.json().data.token);
  
  // 获取变量
  const token = pm.environment.get("token");
  pm.expect(token).to.be.a("string"); // 校验变量类型
});

4. 接口请求时间校验

javascript

运行

pm.test("响应时间<500ms", () => {
  const checkTime = (time) => time < 500; // 箭头函数封装判断逻辑
  pm.expect(checkTime(pm.response.responseTime)).to.be.true;
});

三、注意事项

  1. Postman 脚本环境完全支持 ES6+,箭头函数、Promise、async/await 等均可用;
  2. 单行逻辑用箭头函数更简洁(如你截图中的写法),多行逻辑建议加{}保持可读性;
  3. 断言库基于Chai.js,语法支持expect/should/assert三种风格,优先用expect(最直观)。


javascript

以 Postman 的天气接口断言代码为例,拆解每一行的意思:

javascript

运行

// 1. 验证响应码为200(请求成功)
pm.test("响应码为200", function () {
  pm.response.to.have.status(200);
});
  • pm:Postman 的内置对象(可以理解为 “Postman 工具的工具箱”),所有操作都靠它;
  • pm.test("测试名称", 函数):定义一个测试用例,第一个参数是测试名称(随便写,方便看结果),第二个参数是要执行的测试逻辑;
  • pm.response:代表接口的响应数据(比如状态码、响应体);
  • to.have.status(200):判断响应码是否等于 200(Postman 封装好的语法,不用自己写判断)。

javascript

运行

// 2. 验证返回数据包含“北京”(城市正确)
pm.test("返回数据包含目标城市", function () {
  pm.expect(pm.response.text()).to.include("北京");
});
  • pm.response.text():把接口的响应体转换成文本格式;
  • pm.expect(内容).to.include("北京"):判断文本里是否包含 “北京”(类似 Excel 的 “查找” 功能)。

javascript

运行

// 3. 验证返回数据包含天气核心字段(如温度、日期)
pm.test("返回数据包含天气核心字段", function () {
  const resData = pm.response.json(); // 把响应体转成JSON对象(方便按字段取值)
  pm.expect(resData.result).to.have.property("date"); // 检查是否有“date”字段
  pm.expect(resData.result).to.have.property("temperature"); // 检查是否有“temperature”字段
});
  • const resData = pm.response.json():把 JSON 格式的响应体转成 JS 对象(比如响应是{"result":{"date":"2025-12-24"}},转成对象后可以用resData.result.date直接取日期);
  • have.property("date"):判断resData.result这个对象里是否有 “date” 这个属性(字段)。

三、核心结论(不用死记,会用就行)

  1. 不用把 JS 学透:接口测试里只用 Postman/JMeter 封装好的几个核心 API(pm.test/pm.expect/pm.response),记熟这几个就能覆盖 90% 的场景;
  2. 代码的本质是 “工具的配置”:这些 JS 代码不是 “编程开发”,只是用简单的语法告诉工具 “要验证什么”,比如 “检查响应码是不是 200”“有没有北京这个字”;
  3. 新手先抄后改:先复制现成的代码,把 “北京” 改成你要测的城市,把 “date” 改成你要验证的字段,用熟了再理解语法。

如果需要,我可以帮你整理一份接口测试常用 JS 代码速查表(只有 10 行核心代码,背下来就能



接口测试常用 JavaScript 代码速查表(Postman 专属)

核心覆盖 90% 接口测试场景,无需懂复杂语法,复制 + 改关键词即可用,新手直接上手。

测试场景 核心代码(直接复制) 修改说明
验证响应码为 200 javascript pm.test("响应码为200", function () { pm.response.to.have.status(200); }); 把 200 改成目标状态码(如 400/500)
验证响应包含指定文本 javascript pm.test("包含目标文本", function () { pm.expect(pm.response.text()).to.include("北京"); }); 把 “北京” 改成要验证的文本
验证 JSON 字段存在 javascript pm.test("字段存在", function () { const res = pm.response.json(); pm.expect(res.result).to.have.property("date"); }); res.resultdate为目标字段路径
验证 JSON 字段值等于指定值 javascript pm.test("字段值正确", function () { const res = pm.response.json(); pm.expect(res.result.risk_level).to.eql("高"); }); risk_level和 “高” 为目标字段 / 值
提取变量到环境变量 javascript const res = pm.response.json(); pm.environment.set("token", res.data.token); tokenres.data.token为目标变量 / 路径
验证响应时间<500ms javascript pm.test("响应时间达标", function () { pm.expect(pm.response.responseTime).to.be.below(500); }); 把 500 改成目标响应时间(毫秒)
验证响应格式为 JSON javascript pm.test("响应为JSON格式", function () { pm.response.to.be.json; }); 无需修改,直接用
验证请求头包含指定值 javascript pm.test("请求头正确", function () { pm.expect(pm.response.headers.get("Content-Type")).to.eql("application/json"); }); Content-Type和值为目标头
接口依赖 - 引用环境变量 无需代码,URL/Body 中写{{变量名}}(如{{token}} 变量名需和提取时的名称一致
异常场景 - 验证 400 错误 javascript pm.test("参数错误返回400", function () { pm.response.to.have.status(400); pm.expect(pm.response.text()).to.include("参数错误"); }); 改 400 和 “参数错误” 为目标状态 / 文本

用法说明(新手必看)

  1. 所有代码粘贴到 Postman 的「Tests」标签页;
  2. 执行请求后,在「Test Results」中查看是否通过;
  3. 核心改法:只改代码中引号里的关键词(如 “北京”“date”“高”),其他代码不用动;
  4. 示例:验证 “空气质量接口返回 PM2.5 字段”,只需把 “date” 改成 “pm25” 即可。

实战示例(天气接口全套验证)

javascript

运行

// 1. 基础验证
pm.test("响应码200", () => pm.response.to.have.status(200));
pm.test("响应是JSON", () => pm.response.to.be.json);
pm.test("包含城市名", () => pm.expect(pm.response.text()).to.include("上海"));

// 2. 字段验证
const res = pm.response.json();
pm.test("有温度字段", () => pm.expect(res.result).to.have.property("temperature"));
pm.test("温度值合理", () => pm.expect(res.result.temperature).to.not.eql(""));

// 3. 提取变量(供下一个接口用)
pm.environment.set("city", res.result.city);


断言

接口断言是验证接口返回结果是否符合预期的核心步骤,不同场景下断言维度不同,但核心原则是:覆盖 “基础可用性 + 业务正确性 + 数据合法性”。以下是接口测试中必加的断言维度(按优先级排序),附具体示例和适用场景,新手可直接照搬:

一、核心断言维度(所有接口必加)

断言维度 作用 示例代码(Postman/JS) 适用所有接口的原因
响应状态码 验证接口请求是否 “基础成功” javascript pm.test("响应码200", () => pm.response.to.have.status(200)); 状态码是接口最基础的健康度,200 = 成功,4xx = 参数错,5xx = 服务错
响应格式 验证返回数据格式符合约定 javascript pm.test("响应为JSON", () => pm.response.to.be.json); 接口通常约定返回 JSON/XML,格式错会导致下游解析失败
业务成功标识 验证接口 “业务逻辑” 成功(非仅请求成功) javascript const res = pm.response.json(); pm.test("业务成功", () => pm.expect(res.code).to.eql(0)); 状态码 200 不代表业务成功(如查无数据仍返回 200,但 code=1)

二、业务层断言维度(按场景补充)

1. 数据存在性 / 正确性(查询 / 新增 / 修改接口必加)

场景 断言代码示例
包含指定文本 / 字段 javascript // 包含目标城市 pm.expect(pm.response.text()).to.include("北京"); // 包含核心字段 pm.expect(res.result).to.have.property("temperature");
字段值等于预期 javascript // 风险等级为“高” pm.expect(res.result.risk_level).to.eql("高"); // 新增后ID非空 pm.expect(res.data.id).to.not.be.empty;
字段值范围合法 javascript // 金额≥0 pm.expect(res.data.amount).to.be.at.least(0); // 响应时间<1s pm.expect(pm.response.responseTime).to.be.below(1000);

2. 数据一致性(依赖接口 / 批量接口必加)

场景 断言代码示例
入参和返参一致 javascript // 传入的客户ID和返回的一致 const reqCity = pm.request.url.query.get("city"); pm.expect(res.result.city).to.eql(reqCity);
多接口数据一致 javascript // 上一个接口提取的token,当前接口返回包含该token pm.expect(res.data.token).to.eql(pm.environment.get("token"));

3. 异常场景断言(边界 / 错误用例必加)

场景 断言代码示例
参数缺失返回 400 javascript pm.test("参数缺失返回400", () => pm.response.to.have.status(400)); pm.expect(res.msg).to.include("参数不能为空");
无权限返回 401 javascript pm.test("无权限返回401", () => pm.response.to.have.status(401)); pm.expect(res.msg).to.include("未授权");

三、不同类型接口的断言清单(直接套用)

接口类型 必加断言维度 示例(银行场景)
查询接口(GET) 状态码 + 格式 + 业务成功 + 字段存在 + 值正确 查客户风险等级:验证返回 risk_level = 高、包含 customer_id
新增接口(POST) 状态码 + 格式 + 业务成功 + 新增 ID 非空 + 入参一致 新增客户:验证返回 customer_id、name 和传入一致
修改接口(PUT) 状态码 + 格式 + 业务成功 + 修改后字段值更新 修改客户资产:验证 asset_amount = 修改后的值
删除接口(DELETE) 状态码 + 格式 + 业务成功 + 查询不到该数据 删除客户:验证再次查询返回 “无数据”
批量接口 状态码 + 格式 + 业务成功 + 返回条数符合预期 批量查 10 个客户:验证返回数组长度 = 10

四、断言设计技巧(新手避坑)

  1. 不要断言 “无关字段”:只验证核心业务字段(如金额、状态、ID),不验证随机值(如时间戳、流水号);
  2. 异常场景要反向断言:比如 “参数错误时,断言返回 400 而非 200”,覆盖负面用例;
  3. 避免硬编码敏感值:用变量代替固定值(如pm.environment.get("city")),适配多环境测试;
  4. 断言名称要清晰:比如 “响应码为 200”“客户 ID 和入参一致”,方便失败时快速定位问题。

五、实战示例(银行风险评估接口全套断言)

javascript

运行

// 1. 基础断言
pm.test("响应码200", () => pm.response.to.have.status(200));
pm.test("响应为JSON格式", () => pm.response.to.be.json);

// 2. 业务断言
const res = pm.response.json();
pm.test("业务成功(code=0)", () => pm.expect(res.code).to.eql(0));
pm.test("包含客户ID字段", () => pm.expect(res.data).to.have.property("customer_id"));
pm.test("风险等级为高/中/低", () => {
  const riskLevels = ["高", "中", "低"];
  pm.expect(riskLevels).to.include(res.data.risk_level);
});

// 3. 数据一致性断言
pm.test("客户ID和入参一致", () => {
  const reqId = pm.request.url.query.get("customer_id");
  pm.expect(res.data.customer_id).to.eql(reqId);
});

// 4. 性能断言(可选)
pm.test("响应时间<1秒", () => pm.expect(pm.response.responseTime).to.be.below(1000));

按这个清单加断言,既能覆盖核心场景,又不会冗余,新手可以先从 “状态码 + 业务成功 + 核心字段” 这 3 个基础维度入手,再逐步补充其他维度。




mysql

第一阶段:基础核心语法(09:00-11:00,2 小时,银行基础操作必备)

1. 数据库 / 表基础操作(高频★★★★★)

银行项目需频繁切换库、查看表结构,这是最基础且每天必用的操作

sql

-- 1. 切换指定数据库(银行项目多库隔离:客户库、账务库、流水库)
USE 银行客户数据库名;
-- 2. 查看当前库下所有表
SHOW TABLES;
-- 3. 查看表结构(必用!确认字段类型:金额decimal/手机号varchar/日期datetime)
DESC 客户表; -- 简写,等价于 DESCRIBE 客户表;
2. 单表查询 SELECT(高频★★★★★,银行 80% 操作是查询)

✅ 基础语法(核心中的核心,所有银行数据提取的基础)

sql

-- 语法模板
SELECT [字段1,字段2,.../*]  -- *代表查询所有字段,生产环境尽量写具体字段(效率高)
FROM 表名
[WHERE 筛选条件]            -- 按条件过滤数据(核心)
[ORDER BY 字段 ASC/DESC]    -- 排序:ASC升序(默认)、DESC降序(金额/时间常用)
[LIMIT 起始行, 查询行数];   -- 分页(银行导出报表、分页展示必备)

✅ 银行高频筛选条件运算符(背熟,90% 银行查询会用到)

  • 等值 / 不等值:=(等于)、!=/<>(不等于)→ 查指定客户、指定卡号数据
  • 范围:><>=<= → 查「余额≥50 万」的 VIP 客户、「近 30 天」流水
  • 模糊匹配:LIKE → %匹配任意字符、_匹配单个字符 → 查「手机号以 138 开头」「姓名含 “丽”」的客户
  • 空值判断:IS NULL(为空)、IS NOT NULL(不为空)→ 查「未预留手机号」的客户
  • 多条件组合:AND(且)、OR(或)、NOT(非)→ 核心组合,高频度 100%
3. 增删改语句(高频★★★★,银行账务录入 / 客户信息更新必备)

❗ 银行项目警示:DELETE/UPDATE 必须加 WHERE 条件,否则会清空整张表 / 更新所有数据,属于生产重大事故!

sql

-- 1. 新增数据(INSERT,客户开户、账务入账)
INSERT INTO 表名(字段1,字段2,字段3) VALUES(值1,值2,值3);
-- 2. 更新数据(UPDATE,客户手机号/地址修改、账户余额更新)
UPDATE 表名 SET 字段1=新值,字段2=新值 WHERE 筛选条件; -- 必须加WHERE!
-- 3. 删除数据(DELETE,销户操作)
DELETE FROM 表名 WHERE 筛选条件; -- 必须加WHERE!


第二阶段:进阶核心语法(11:00-14:00,3 小时含午休,银行统计 / 对账必备)

此阶段是银行项目分水岭,80% 的银行 SQL 需求(统计报表、对账、数据汇总)均依赖这些语法,必须吃透 + 大量练习!

✅ 必学知识点(按银行高频度排序,优先级从高到低)

1. 聚合函数(高频★★★★★,银行统计核心,无死角掌握)

✅ 5 个核心聚合函数(银行报表 100% 用到,背熟用法),搭配 AS 给结果起别名(报表必备)

sql

COUNT(*)  -- 统计行数 → 统计客户数、交易笔数
SUM(字段)  -- 求和 → 统计总交易金额、总存款余额
AVG(字段)  -- 平均值 → 统计客户平均余额、平均交易金额
MAX(字段)  -- 最大值 → 最大单笔交易、最高账户余额
MIN(字段)  -- 最小值 → 最小单笔存款、最低账户余额

✅ 银行高频示例:

sql

-- 统计所有成功交易的总金额,别名「总交易金额」
SELECT SUM(trans_amount) AS 总交易金额 FROM t_transaction WHERE trans_status='成功';
-- 统计储蓄卡账户的平均余额
SELECT AVG(balance) AS 储蓄卡平均余额 FROM t_account WHERE acc_type='储蓄卡';
2. 分组查询 GROUP BY + 分组筛选 HAVING(高频★★★★★,银行核心统计)

✅ 核心逻辑:先分组,再统计;先 WHERE 筛选行,再 HAVING 筛选分组结果✅ 语法模板(银行必背):

sql

SELECT 分组字段, 聚合函数(统计字段) AS 别名
FROM 表名
WHERE 行筛选条件  -- 筛选单条数据,执行在分组前
GROUP BY 分组字段  -- 按指定字段分组(客户类型、账户类型、交易类型)
HAVING 分组筛选条件; -- 筛选分组结果,必须搭配聚合函数,执行在分组后

✅ 银行高频示例:

sql

-- 按交易类型分组,统计每种交易的总金额,且只显示总金额≥100万的分组
SELECT trans_type, SUM(trans_amount) AS 交易总金额
FROM t_transaction
WHERE trans_status='成功'
GROUP BY trans_type
HAVING SUM(trans_amount) >= 1000000;
3. 多表连接查询(高频★★★★★,银行对账 / 关联查询核心)

银行数据均为关联存储(客户→账户→流水),多表连接是项目中最常用的高级语法,3 种核心连接必须吃透:

sql

-- 1. INNER JOIN 内连接 → 只查「两张表都匹配」的数据(对账核心,最常用)
SELECT 字段 FROM 表1 INNER JOIN 表2 ON 表1.关联字段 = 表2.关联字段;
-- 2. LEFT JOIN 左连接 → 查「左表所有数据 + 右表匹配数据」(客户-账户关联,必用)
SELECT 字段 FROM 表1 LEFT JOIN 表2 ON 表1.关联字段 = 表2.关联字段;
-- 3. RIGHT JOIN 右连接 → 查「右表所有数据 + 左表匹配数据」(流水-账户关联)
SELECT 字段 FROM 表1 RIGHT JOIN 表2 ON 表1.关联字段 = 表2.关联字段;

✅ 银行核心示例(对账场景):

sql

-- 关联3张表,查询「VIP客户」的姓名、银行卡号、近30天交易金额,按交易金额降序
SELECT c.cust_name, a.acc_no, t.trans_amount
FROM t_customer c
INNER JOIN t_account a ON c.cust_id = a.cust_id
INNER JOIN t_transaction t ON a.acc_id = t.acc_id
WHERE c.cust_type='VIP' AND t.trans_time >= DATE_SUB(NOW(), INTERVAL 30 DAY)
ORDER BY t.trans_amount DESC;
4. 子查询(高频★★★★,银行复杂条件筛选核心)

✅ 定义:查询中嵌套查询,内层查询结果作为外层查询的「条件 / 数据源」,解决银行复杂筛选需求(如:查「余额高于平均余额」的客户)✅ 2 种常用形式(银行必用):

sql

-- 形式1:子查询作为WHERE条件(用IN/=/>/<等运算符)
SELECT * FROM 表1 WHERE 字段 IN (SELECT 字段 FROM 表2 WHERE 条件);
-- 形式2:子查询作为临时表(FROM后,需起别名)
SELECT * FROM (SELECT 字段 FROM 表1 WHERE 条件) AS 临时表名 WHERE 条件;

✅ 银行高频示例:

sql

-- 查询余额高于「所有账户平均余额」的储蓄卡账户(子查询求平均余额)
SELECT acc_no, balance FROM t_account 
WHERE acc_type='储蓄卡' AND balance > (SELECT AVG(balance) FROM t_account);

第三阶段:高级实战语法 + 银行项目综合刷题(14:00-17:00,3 小时,学完直接落地)

此阶段是银行项目拔高内容,覆盖复杂统计、性能优化、特殊场景处理,学完即可独立完成银行项目中 99% 的 SQL 需求,配套 10 道综合大题(银行真实场景复刻)。

✅ 必学高级知识点(银行项目高频难点,直击痛点)

1. 分页查询优化(高频★★★★★,银行报表 / 分页展示必备)

银行数据量极大(千万级流水、百万级客户),LIMIT 基础分页效率低,银行最优分页写法(基于主键自增):

sql

-- 低效写法(大数据量卡顿)
SELECT * FROM t_transaction LIMIT 10000, 10; -- 跳过1万行,查10行
-- 高效写法(银行生产环境必用,主键过滤)
SELECT * FROM t_transaction WHERE trans_id > 10000 LIMIT 10;
2. 日期函数(高频★★★★★,银行时间筛选核心)

银行所有数据均需按时间筛选(日 / 周 / 月 / 季 / 年报表),背熟以下 5 个核心日期函数:

sql

NOW()         -- 获取当前时间(datetime)→ 2026-01-02 15:30:00
DATE(NOW())   -- 提取日期部分 → 2026-01-02
DATE_SUB(NOW(), INTERVAL 30 DAY) -- 30天前的时间(近30天流水)
YEAR/DATE/HOUR -- 提取年/日/小时 → YEAR(trans_time)=2025
DATEDIFF(日期1,日期2) -- 计算两个日期的天数差 → 客户开户天数
3. CASE WHEN 条件判断(高频★★★★,银行报表多维度统计)

✅ 核心作用:一行内实现多条件统计,银行报表必备(如:统计不同区间的客户数、不同金额的交易笔数)✅ 银行示例:

sql

-- 统计账户余额区间分布:0-1万、1-10万、10万以上
SELECT
COUNT(CASE WHEN balance<=10000 THEN 1 END) AS '0-1万',
COUNT(CASE WHEN balance>10000 AND balance<=100000 THEN 1 END) AS '1-10万',
COUNT(CASE WHEN balance>100000 THEN 1 END) AS '10万以上'
FROM t_account;
4. DISTINCT 去重(高频★★★★,银行数据去重)

✅ 核心作用:去除重复数据,银行场景:查询「有交易的唯一客户数」「唯一卡号数」

sql

-- 查询有过交易的唯一客户数
SELECT COUNT(DISTINCT c.cust_id) AS 交易客户数
FROM t_customer c JOIN t_account a ON c.cust_id=a.cust_id
JOIN t_transaction t ON a.acc_id=t.acc_id;



case

一、版本 1 ✅ 你的原 SQL「补全 ELSE」版(直接复制执行)

完美适配你的余额区间统计需求,手动加ELSE兜底,逻辑更严谨、结果更清晰,执行结果和原 SQL 一致,但可读性 / 健壮性翻倍:

sql

SELECT
	-- 余额0-1万:满足条件返回1,不满足返回NULL
	COUNT(CASE WHEN balance <= 10000 THEN 1 ELSE NULL END) AS '0-1万',
	-- 余额1-10万:满足条件返回1,不满足返回NULL
	COUNT(CASE WHEN balance > 10000 AND balance <= 100000 THEN 1 ELSE NULL END) AS '1-10万',
	-- 余额10万以上:满足条件返回1,不满足返回NULL
	COUNT(CASE WHEN balance > 100000 THEN 1 ELSE NULL END) AS '10万以上'
FROM t_account;

✅ 核心讲解:ELSE在这里的作用

  1. 你的原 SQL 没写ELSE → MySQL 默认返回NULL,和上面写ELSE NULL效果完全一样;
  2. 手动加ELSE NULL是「显式写法」,好处是:代码逻辑一目了然,团队协作时别人能立刻看懂你的判断规则,这是企业里的规范写法;
  3. 配合COUNT()使用:COUNT()只统计非 NULL 值NULL会被直接忽略 → 刚好实现「符合条件就计数,不符合就不计」。

二、版本 2 ✅ CASE WHEN+ELSE完整语法版(企业级必用,拓展学习)

这是CASE WHEN的 完整标准写法,包含WHEN 多条件 + ELSE 兜底 + END,能应对更复杂的业务场景,也是工作中最常用的写法,建议重点掌握:

✅ 示例 1:余额统计(带 ELSE 兜底,分类无遗漏)

sql

SELECT
	-- 完整CASE WHEN结构:多条件+ELSE兜底
	COUNT(CASE 
		WHEN balance <= 10000 THEN 1
		WHEN balance > 10000 AND balance <= 100000 THEN 1
		WHEN balance > 100000 THEN 1
		ELSE NULL  -- 兜底:所有不满足上述条件的情况,统一返回NULL
	END) AS '有效账户总数',
	
	-- 单独统计:异常余额(比如负数、0)
	COUNT(CASE WHEN balance <= 0 THEN 1 ELSE NULL END) AS '异常余额账户'
FROM t_account;

✅ 示例 2:拓展场景(账户类型 + 余额双条件,ELSE 实战)

结合你的银行表,写一个更贴近业务的案例,帮你举一反三:

sql

SELECT
	-- 统计:储蓄卡不同余额区间数量
	COUNT(CASE WHEN acc_type='储蓄卡' AND balance <=10000 THEN 1 ELSE NULL END) AS '储蓄卡_0-1万',
	COUNT(CASE WHEN acc_type='储蓄卡' AND balance >100000 THEN 1 ELSE NULL END) AS '储蓄卡_10万以上',
	-- 统计:信用卡/理财账户(ELSE合并兜底)
	COUNT(CASE WHEN acc_type!='储蓄卡' THEN 1 ELSE NULL END) AS '其他账户总数'
FROM t_account;

🎯 必记!CASE WHEN完整语法规则(2 种写法,全覆盖)

✅ 写法 1:【搜索式 CASE】(最常用,你用的就是这种)

👉 适用场景:多条件判断、范围判断(比如区间、多字段组合条件),也是企业开发 99% 的场景用法

sql

CASE
    WHEN 条件表达式1 THEN 返回值1
    WHEN 条件表达式2 THEN 返回值2
    WHEN 条件表达式3 THEN 返回值3
    ...
    ELSE 兜底返回值  -- 可选,不写默认返回NULL
END

✅ 核心特点:WHEN后接完整条件表达式(可以用>、<、AND、OR、=等所有运算符),非常灵活。

✅ 写法 2:【简单式 CASE】(特殊场景用)

👉 适用场景:字段等于固定值的判断(比如性别、账户类型、客户等级),写法更简洁

sql

CASE 待判断字段名
    WHEN 固定值1 THEN 返回值1
    WHEN 固定值2 THEN 返回值2
    WHEN 固定值3 THEN 返回值3
    ...
    ELSE 兜底返回值  -- 可选,不写默认返回NULL
END

✅ 举个例子(统计不同账户类型数量):

sql

SELECT
	COUNT(CASE acc_type WHEN '储蓄卡' THEN 1 ELSE NULL END) AS '储蓄卡',
	COUNT(CASE acc_type WHEN '信用卡' THEN 1 ELSE NULL END) AS '信用卡',
	COUNT(CASE acc_type WHEN '理财账户' THEN 1 ELSE NULL END) AS '理财账户',
	COUNT(CASE acc_type ELSE 1 END) AS '未知账户'  -- ELSE兜底
FROM t_account;

🎯 关键知识点总结(3 个核心,记牢不踩坑)

✅ 1. ELSE的核心价值(为什么一定要加?)

  • ✔️ 兜底防遗漏:确保所有数据都能被判断,不会出现「无匹配结果」的情况;
  • ✔️ 逻辑更严谨:明确「不满足条件时的返回值」,避免因 MySQL 默认NULL导致的统计错误;
  • ✔️ 可读性更强:团队协作时,别人能一眼看懂你的完整判断规则。

✅ 2. CASE WHENCOUNT()搭配的底层原理(必懂)

  • CASE WHEN满足条件 → 返回1(非 NULL 值),不满足 → 返回NULL
  • COUNT(字段/值) → 只统计非 NULL 值的数量,自动忽略NULL
  • ✅ 两者搭配 → 完美实现「符合条件就计数,不符合就跳过」,这是 SQL 区间统计的经典写法!

✅ 3. 语法铁律(绝对不能错)

  1. CASE开头,必须以END结尾(少一个都报错!);
  2. ELSE是可选的,不写则默认返回NULL
  3. THEN后只能跟「单个值」(数字 / 字符串 / NULL),不能写复杂语句;
  4. CASE WHEN可以嵌套、可以和任何聚合函数(COUNT/SUM/AVG)搭配。

✅ 额外福利:3 个企业级高频实战案例(直接套用)

基于你的银行表,再给 3 个工作中常用的CASE WHEN+ELSE案例,练完直接上手项目:

案例 1:统计客户等级 + 账户余额(双维度)

sql

SELECT
	c.cust_type AS '客户等级',
	COUNT(CASE WHEN a.balance>0 THEN 1 ELSE NULL END) AS '有余额账户数',
	SUM(CASE WHEN a.balance>0 THEN a.balance ELSE 0 END) AS '总余额'
FROM t_customer c
JOIN t_account a ON c.cust_id=a.cust_id
GROUP BY c.cust_type;

案例 2:交易状态分类统计(ELSE 合并异常)

sql

SELECT
	COUNT(CASE WHEN trans_status='成功' THEN 1 ELSE NULL END) AS '成功交易',
	COUNT(CASE WHEN trans_status='失败' THEN 1 ELSE NULL END) AS '失败交易',
	COUNT(CASE ELSE 1 END) AS '其他状态交易'  -- ELSE兜底所有剩余情况
FROM t_transaction;

案例 3:余额分级打标签(ELSE 统一标为「普通」)

sql

SELECT
	acc_no AS '银行卡号',
	balance AS '账户余额',
	-- CASE WHEN打标签,ELSE兜底
	CASE
		WHEN balance >= 500000 THEN '高净值账户'
		WHEN balance >=100000 THEN '优质账户'
		WHEN balance >=10000 THEN '普通账户'
		ELSE '小额账户'  -- 所有不满足的,统一标为小额
	END AS '账户等级标签'
FROM t_account;

✨ 最终总结

  1. 你的原 SQL ✅ 本质是CASE WHEN的「简化写法」,省略ELSE默认返回NULL
  2. 工作中 ✅ 建议显式写ELSE,逻辑更严谨,是团队规范;
  3. CASE WHEN核心搭配 ✅ COUNT/SUM/AVG做条件统计,是 SQL 面试 / 工作必考的知识点;
  4. 记住 2 种写法 ✅ 「搜索式」(范围判断)+「简单式」(等值判断),覆盖所有场景。

以上所有 SQL 都能直接复制到你的 Navicat 执行,放心用~ 😊




limit 用法

✅ MySQL LIMIT 用法 超全详解(结合你的 SQL + 实操案例,一看就会)

✅ 先给你最核心的结论(对应你的 SQL)

你的语句里 LIMIT 10,10 → ✔️ 跳过前 10 条结果,只获取后续的 10 条数据,是 MySQL 分页查询的核心写法,也是工作中最常用的格式!结合你的业务:查询 2025 年 12 月私行客户理财交易、按交易时间倒序后,取第 11~20 条数据(最新的前 10 条跳过,拿下一批 10 条)。


一、LIMIT 完整语法(2 种写法,全部掌握)

LIMIT 是 MySQL 专属的结果集行数限制关键字,作用就是「控制查询结果返回多少行、从哪一行开始返回」,无兼容性问题,所有 MySQL 版本通用,分 2 种写法:

✅ 写法 1:LIMIT 跳过行数, 读取行数(你的 SQL 用的这种,分页专用)

sql

# 语法格式
SELECT ... FROM ... WHERE ... ORDER BY ... LIMIT M, N;

✅ 含义拆解:

  • M要跳过的行数(从 0 开始计数,第一行是 0、第二行是 1...);

  • N要读取的行数(最终返回给你的数据条数);

    ✅ 你的案例对应:LIMIT 10,10 → M=10,N=10 → 跳过前 10 行,读 10 行 → 结果就是第 11~20 条

✅ 写法 2:LIMIT 读取行数(最简写法,取前 N 条)

sql

# 语法格式
SELECT ... FROM ... WHERE ... ORDER BY ... LIMIT N;

✅ 含义:直接返回排序后的前 N 条数据,等价于 LIMIT 0, N;✅ 实操示例(适配你的业务):

sql

-- 取私行客户12月理财交易,最新的前10条(常用!)
SELECT c.cust_name, a.acc_no, t.trans_amount, t.trans_time
FROM t_customer c JOIN t_account a ON c.cust_id=a.cust_id
JOIN t_transaction t ON a.acc_id=t.acc_id
WHERE c.cust_type='私行' AND t.trans_type='理财' 
AND YEAR(t.trans_time)=2025 AND MONTH(t.trans_time)=12
ORDER BY t.trans_time DESC LIMIT 10;

二、✅ 分页查询核心规律(必背!工作 100% 用得上)

LIMIT M,N 是分页功能的底层实现,比如前端页面「每页显示 10 条,点第 1 页 / 第 2 页 / 第 3 页」,本质就是改 M 的值,规律超简单:

✅ 公式:LIMIT (页码-1)*每页条数 , 每页条数

结合你的案例(每页 10 条):

  • 第 1 页:LIMIT 0,10 → 跳过 0 条,读 10 条 → 1~10 条
  • 第 2 页:LIMIT 10,10 → 跳过 10 条,读 10 条 →11~20 条
  • 第 3 页:LIMIT 20,10 → 跳过 20 条,读 10 条 →21~30 条
  • 第 N 页:LIMIT (N-1)*10,10

✅ 拓展:如果你的需求是「每页 20 条,查第 5 页」,直接套公式:LIMIT (5-1)*20,20 → LIMIT 80,20


三、✅ 关键注意事项(避坑必备,3 个核心)

✅ 1. LIMIT 必须写在 SQL 语句的最后面

语法铁律,顺序不能乱!正确执行顺序:SELECT → FROM → JOIN → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT你的语句顺序是完美的 ✔️,严格遵守了这个规则,这是LIMIT生效的前提!

✅ 2. LIMIT 生效前,会先执行 ORDER BY 排序

✅ 核心逻辑:先排序、再分页,这是分页的意义!你的语句先执行 ORDER BY t.trans_time DESC(交易时间倒序,最新的在前),再执行 LIMIT 10,10,拿到的就是「最新的第 11~20 条」;如果不排序直接用LIMIT,返回的结果是随机的,毫无意义 ❌。

✅ 3. 跳过行数 M 可以为 0,不能为负数

  • LIMIT 0,10 ✔️ 合法,等价于 LIMIT 10
  • LIMIT -5,10 ❌ 报错,MySQL 不支持负数的跳过行数。

四、✅ 进阶用法(MySQL8.0+ 推荐,更易读)

MySQL8.0 及以上版本,支持 LIMIT N OFFSET M 写法,和 LIMIT M,N 完全等价,只是换了个顺序,可读性更强(一眼能看出「取 N 条、跳过 M 条」):

sql

# 两种写法 结果完全一致
LIMIT 10,10;
LIMIT 10 OFFSET 10; -- 推荐:取10条,跳过10条

✅ 适配你的 SQL 的写法:

sql

SELECT c.cust_name, a.acc_no, t.trans_amount, t.trans_time
FROM t_customer c JOIN t_account a ON c.cust_id=a.cust_id
JOIN t_transaction t ON a.acc_id=t.acc_id
WHERE c.cust_type='私行' AND t.trans_type='理财' 
AND YEAR(t.trans_time)=2025 AND MONTH(t.trans_time)=12
ORDER BY t.trans_time DESC LIMIT 10 OFFSET 10;

五、✅ 3 个实战案例(直接复制执行,练会为止)

✅ 案例 1:基础用法 → 取储蓄卡余额最高的前 5 个账户

sql

SELECT acc_no, balance 
FROM t_account 
WHERE acc_type='储蓄卡' 
ORDER BY balance DESC 
LIMIT 5; -- 直接取前5条

✅ 案例 2:分页用法 → 取客户姓名按 A-Z 排序,第 3 页(每页 8 条)

sql

SELECT cust_id, cust_name 
FROM t_customer 
ORDER BY cust_name ASC 
LIMIT 16,8; -- (3-1)*8=16 → 跳过16条,取8条

✅ 案例 3:结合业务 → 取 2025 年 12 月交易金额 > 10 万的前 3 条理财交易

sql

SELECT c.cust_name, t.trans_amount, t.trans_time
FROM t_customer c 
JOIN t_account a ON c.cust_id=a.cust_id
JOIN t_transaction t ON a.acc_id=t.acc_id
WHERE t.trans_type='理财' AND t.trans_amount>100000
AND YEAR(t.trans_time)=2025 AND MONTH(t.trans_time)=12
ORDER BY t.trans_amount DESC 
LIMIT 3; -- 取金额最高的前3条

✨ 最终总结(30 秒记牢所有核心)

  1. LIMIT N → 取排序后的前 N 条,最常用、最简写法;
  2. LIMIT M,N → 跳过 M 条,取 N 条,分页专用,公式:(页码-1)*每页条数, 每页条数
  3. LIMIT N OFFSET M → MySQL8.0 + 推荐,和LIMIT M,N等价,可读性更强;
  4. 铁律:LIMIT 必须写在 SQL最后,且必须配合ORDER BY使用才有意义。

Hello World

posted on 2026-01-08 14:03  布丁家的苏苏  阅读(65)  评论(0)    收藏  举报