售后服务
我们是专业的

Day 11上午:SQL基础 - 打开数据宝库的万能钥匙

一个让人绝望的深夜加班

2024年3月的某个周五晚上9点,售后数据分析师张伟盯着电脑屏幕,眼神涣散。

老板下午突然要一份报告:"找出过去6个月,在华东区所有门店,维修过3次以上的客户,他们的车型分布、平均维修费用、以及最常见的故障类型。明天上午10点要。"

张伟的痛苦:

  • 数据在数据库里:23万条工单记录、15万条客户记录、8万条配件记录
  • Excel打不开:导出的CSV文件有500MB,Excel直接卡死
  • 手工筛选?:用筛选器?要筛选多少次?怎么统计"维修过3次以上"?

他向隔壁的技术部同事小李求助。小李说:"这不就是3行SQL的事儿吗?"

10分钟后,小李写了这段代码:

SELECT 
    c.车型,
    COUNT(DISTINCT w.客户ID) as 客户数量,
    AVG(w.维修费用) as 平均费用,
    f.故障类型,
    COUNT(f.故障类型) as 故障次数
FROM 工单表 w
JOIN 客户表 c ON w.客户ID = c.客户ID
JOIN 故障表 f ON w.工单号 = f.工单号
WHERE w.门店区域 = '华东区'
    AND w.维修日期 >= DATE_SUB(NOW(), INTERVAL 6 MONTH)
    AND w.客户ID IN (
        SELECT 客户ID 
        FROM 工单表 
        WHERE 门店区域 = '华东区'
        GROUP BY 客户ID 
        HAVING COUNT(*) >= 3
    )
GROUP BY c.车型, f.故障类型
ORDER BY 客户数量 DESC;

3秒钟,结果出来了。

张伟看着屏幕上整齐的数据,感受到了一种从未有过的震撼:"这就是SQL的力量?"


SQL是什么?为什么售后运营人必须学?

SQL(Structured Query Language,结构化查询语言):一种专门用于管理和操作关系型数据库的标准化语言。它能让你用接近自然语言的方式,从海量数据中精准提取你想要的信息。

为什么Excel不够用?

对比维度 Excel SQL数据库
数据量上限 约100万行 数十亿行
处理速度 1万行以上明显变慢 百万行秒级查询
多表关联 VLOOKUP容易出错 JOIN语句精准高效
复杂条件筛选 多层嵌套IF公式难维护 WHERE语句清晰易读
数据更新 手工维护,易出错 自动同步,实时准确
团队协作 多人编辑冲突 多人同时查询无影响

真实场景

  • Excel适合:几千行的临时分析、制作报表、可视化展示
  • SQL适合:从源头取数、多表关联、复杂条件筛选、大数据量处理

SQL的第一课:SELECT - 我要什么数据?

最基础的查询

场景:你想看看工单表里都有什么数据

SELECT * FROM 工单表;

解读

  • SELECT:我要选取(查询)
  • *:所有列(星号是通配符)
  • FROM:从哪个表
  • 工单表:表名
  • ;:SQL语句结束符号

指定需要的列(提高效率)

场景:我只需要工单号、客户姓名、维修费用这三列

SELECT 
    工单号,
    客户姓名,
    维修费用
FROM 工单表;

为什么要指定列?

  • 减少数据传输量(网络更快)
  • 提高查询速度(数据库只读取需要的列)
  • 代码更清晰(一眼看出要什么数据)

WHERE条件:精准定位你要的数据

单条件筛选

场景1:找出所有"深圳南山店"的工单

SELECT 
    工单号,
    客户姓名,
    维修日期,
    维修费用
FROM 工单表
WHERE 门店名称 = '深圳南山店';

场景2:找出维修费用超过5000元的工单

SELECT 
    工单号,
    客户姓名,
    维修费用
FROM 工单表
WHERE 维修费用 > 5000;

多条件组合(AND、OR)

场景3:找出深圳南山店,且费用超过5000元的工单

SELECT 
    工单号,
    客户姓名,
    维修费用
FROM 工单表
WHERE 门店名称 = '深圳南山店'
    AND 维修费用 > 5000;

场景4:找出深圳南山店或广州天河店的工单

SELECT 
    工单号,
    客户姓名,
    门店名称
FROM 工单表
WHERE 门店名称 = '深圳南山店'
    OR 门店名称 = '广州天河店';

更优雅的写法(IN)

SELECT 
    工单号,
    客户姓名,
    门店名称
FROM 工单表
WHERE 门店名称 IN ('深圳南山店', '广州天河店', '东莞松山湖店');

日期范围筛选

场景5:找出2024年3月的所有工单

SELECT 
    工单号,
    客户姓名,
    维修日期
FROM 工单表
WHERE 维修日期 >= '2024-03-01'
    AND 维修日期 < '2024-04-01';

更简洁的写法(BETWEEN)

SELECT 
    工单号,
    客户姓名,
    维修日期
FROM 工单表
WHERE 维修日期 BETWEEN '2024-03-01' AND '2024-03-31';

模糊搜索(LIKE)

场景6:找出所有特斯拉车型的工单

SELECT 
    工单号,
    客户姓名,
    车型
FROM 工单表
WHERE 车型 LIKE '%特斯拉%';

通配符说明

  • %:代表任意多个字符
  • _:代表单个字符

示例

  • LIKE '特斯拉%':特斯拉开头(特斯拉Model 3、特斯拉Model Y)
  • LIKE '%Model 3':Model 3结尾
  • LIKE '%Model_':Model后面跟一个字符(Model 3、Model Y、Model X)

实战案例一:诊断门店服务问题

业务背景

运营总监凌晨2点打电话:"华南区客户投诉激增,马上查出哪些门店、哪些服务类型、哪些时间段的等待时长超标!"

传统Excel做法(需要2小时)

  1. 导出华南区所有工单数据(卡住10分钟)
  2. 手工计算等待时长(实际开始时间 - 预约时间)
  3. 筛选等待时长>60分钟的记录
  4. 按门店、服务类型分组统计
  5. 制作数据透视表

SQL做法(3分钟)

-- 查询华南区等待时长超过60分钟的工单分布
SELECT 
    门店名称,
    服务类型,
    COUNT(*) as 超时工单数,
    AVG(TIMESTAMPDIFF(MINUTE, 预约时间, 实际开始时间)) as 平均等待时长,
    MAX(TIMESTAMPDIFF(MINUTE, 预约时间, 实际开始时间)) as 最长等待时长
FROM 工单表
WHERE 门店区域 = '华南区'
    AND 维修日期 >= DATE_SUB(NOW(), INTERVAL 7 DAY)  -- 最近7天
    AND TIMESTAMPDIFF(MINUTE, 预约时间, 实际开始时间) > 60  -- 等待超过60分钟
GROUP BY 门店名称, 服务类型
ORDER BY 超时工单数 DESC;

查询结果

门店名称 服务类型 超时工单数 平均等待时长 最长等待时长
广州天河店 维修 45 85分钟 180分钟
广州天河店 钣喷 38 92分钟 210分钟
深圳福田店 维修 12 68分钟 95分钟

SQL代码解读

  1. TIMESTAMPDIFF函数:计算两个时间之间的差值
    • TIMESTAMPDIFF(MINUTE, 开始时间, 结束时间):以分钟为单位计算差值
    • 其他单位:SECOND(秒)、HOUR(小时)、DAY(天)
  2. DATE_SUB函数:日期减法
    • DATE_SUB(NOW(), INTERVAL 7 DAY):当前时间减去7天
    • NOW():当前日期时间
  3. GROUP BY:分组统计(类似Excel数据透视表的行标签)
  4. ORDER BY ... DESC:按降序排列(问题最严重的排最前面)

JOIN多表关联:把散落的数据拼成完整故事

为什么需要多表关联?

现实情况:数据分散在多个表里

  • 工单表:有工单号、客户ID、维修日期、费用
  • 客户表:有客户ID、姓名、电话、车型、购车日期
  • 技师表:有技师ID、姓名、技能等级、入职日期
  • 配件表:有工单号、配件名称、配件费用

业务需求:我想知道"购车3年以上的客户,平均维修费用是多少?"

→ 需要关联工单表客户表(通过客户ID)

JOIN的四种类型

1. INNER JOIN(内连接)- 只要交集

规则:只保留两边都有的记录

示例:找出既有工单记录,又有客户信息的数据

SELECT 
    w.工单号,
    w.维修日期,
    w.维修费用,
    c.客户姓名,
    c.车型,
    c.购车日期
FROM 工单表 w
INNER JOIN 客户表 c ON w.客户ID = c.客户ID;

结果

  • 有工单但客户信息已删除 → 不显示
  • 客户存在但从未维修过 → 不显示
  • 客户存在且有维修记录 → 显示

2. LEFT JOIN(左连接)- 以左表为主

规则:保留左表所有记录,右表没有的用NULL填充

示例:找出所有客户及他们的维修记录(包括从未维修的客户)

SELECT 
    c.客户姓名,
    c.车型,
    c.购车日期,
    w.工单号,
    w.维修日期,
    w.维修费用
FROM 客户表 c
LEFT JOIN 工单表 w ON c.客户ID = w.客户ID;

结果

  • 所有客户都会显示
  • 从未维修的客户,工单信息显示为NULL

业务用途:找出"从未来过售后的客户"(流失预警)

SELECT 
    c.客户姓名,
    c.车型,
    c.购车日期
FROM 客户表 c
LEFT JOIN 工单表 w ON c.客户ID = w.客户ID
WHERE w.工单号 IS NULL  -- 工单号为空,说明从未维修
    AND c.购车日期 < DATE_SUB(NOW(), INTERVAL 1 YEAR);  -- 购车超过1年

3. RIGHT JOIN(右连接)- 以右表为主

(与LEFT JOIN相反,实际工作中较少使用,通常把表顺序调换后用LEFT JOIN)

4. FULL OUTER JOIN(全外连接)- 要所有记录

规则:保留两边所有记录,没有匹配的用NULL填充

注意:MySQL不直接支持FULL OUTER JOIN,需要用UNION模拟,实际工作中很少用。


实战案例二:找出"问题车辆"和"问题客户"

业务背景

质量部门要求:"找出过去6个月维修频次异常的车辆和客户,分析是车辆质量问题还是使用问题。"

SQL实现

-- 找出维修3次以上的客户及其车辆信息
SELECT 
    c.客户姓名,
    c.手机号,
    c.车型,
    c.购车日期,
    TIMESTAMPDIFF(MONTH, c.购车日期, NOW()) as 车龄_月,
    COUNT(w.工单号) as 维修次数,
    SUM(w.维修费用) as 累计费用,
    AVG(w.维修费用) as 平均单次费用,
    GROUP_CONCAT(DISTINCT w.故障描述 SEPARATOR '; ') as 故障清单
FROM 客户表 c
INNER JOIN 工单表 w ON c.客户ID = w.客户ID
WHERE w.维修日期 >= DATE_SUB(NOW(), INTERVAL 6 MONTH)
GROUP BY c.客户ID, c.客户姓名, c.手机号, c.车型, c.购车日期
HAVING COUNT(w.工单号) >= 3  -- 维修3次以上
ORDER BY 维修次数 DESC, 累计费用 DESC;

查询结果示例

客户姓名 车型 车龄_月 维修次数 累计费用 故障清单
王先生 某品牌Model X 8 5 15,680 电池故障; 悬挂异响; 刹车异常; 电池故障
李女士 某品牌Model 3 14 4 8,200 轮胎磨损; 常规保养; 空调故障

代码解读

  1. TIMESTAMPDIFF(MONTH, ...): 计算车龄(以月为单位)
  2. COUNT(w.工单号): 统计维修次数
  3. SUM(w.维修费用): 累计费用
  4. GROUP_CONCAT: 把多行合并成一行,用分号分隔
    • 例如:把5次维修的故障描述合并成一个字符串
  5. HAVING: 对分组后的结果进行筛选
    • 注意:WHERE是分组前筛选,HAVING是分组后筛选

业务洞察

质量部门看到数据后发现:

发现1:王先生的车出现2次"电池故障"→ 可能是质量问题

  • 行动:联系厂家技术支持,申请深度检测

发现2:李女士的车龄14个月,维修4次,但都是正常磨损和保养

  • 行动:正常,无需特殊关注

这就是SQL+业务思维的威力:不是单纯看"维修次数多"就判定有问题,而是要结合故障类型、车龄、费用综合分析。


常用SQL函数速查

日期时间函数

-- 当前日期时间
NOW()                          -- 2024-03-15 14:30:25
CURDATE()                      -- 2024-03-15
CURTIME()                      -- 14:30:25

-- 日期计算
DATE_ADD(日期, INTERVAL 7 DAY)   -- 加7天
DATE_SUB(日期, INTERVAL 1 MONTH) -- 减1个月
TIMESTAMPDIFF(DAY, 开始, 结束)    -- 计算天数差

-- 日期格式化
DATE_FORMAT(日期, '%Y年%m月%d日')  -- 2024年03月15日

字符串函数

-- 拼接
CONCAT(字段1, '-', 字段2)        -- 拼接字符串

-- 截取
SUBSTRING(字段, 1, 5)           -- 截取前5个字符
LEFT(字段, 3)                   -- 左边3个字符
RIGHT(字段, 4)                  -- 右边4个字符

-- 查找替换
REPLACE(字段, '旧值', '新值')    -- 替换
TRIM(字段)                      -- 去除前后空格
LOWER(字段)                     -- 转小写
UPPER(字段)                     -- 转大写

数值函数

-- 四舍五入
ROUND(费用, 2)                  -- 保留2位小数
CEIL(费用)                      -- 向上取整
FLOOR(费用)                     -- 向下取整

-- 统计函数
COUNT(*)                        -- 计数(包括NULL)
COUNT(字段)                     -- 计数(不包括NULL)
SUM(费用)                       -- 求和
AVG(费用)                       -- 平均值
MAX(费用)                       -- 最大值
MIN(费用)                       -- 最小值

实战练习:30分钟挑战

场景设定

你是售后运营分析师,数据库里有以下表:

工单表(service_orders):

  • 工单号(order_id)
  • 客户ID(customer_id)
  • 门店ID(store_id)
  • 技师ID(technician_id)
  • 维修日期(service_date)
  • 维修费用(service_cost)
  • 服务类型(service_type):保养、小修、大修、钣喷

客户表(customers):

  • 客户ID(customer_id)
  • 客户姓名(customer_name)
  • 车型(car_model)
  • 购车日期(purchase_date)

任务清单

□ 任务1:查询2024年3月的所有工单,只显示工单号、客户ID、维修费用

□ 任务2:找出维修费用超过10000元的所有工单,按费用降序排列

□ 任务3:统计每个门店在2024年3月的工单数量和总费用

□ 任务4:找出购车时间超过2年,但从未来过售后的客户

□ 任务5:找出维修次数最多的前10名客户,显示他们的姓名、车型、维修次数、累计费用


常见错误与避坑指南

错误1:忘记WHERE条件,查询全表

错误示例

SELECT * FROM 工单表;  -- 危险!可能返回几百万行

正确做法

-- 总是加上限制条件
SELECT * FROM 工单表
WHERE 维修日期 >= '2024-03-01'
LIMIT 100;  -- 限制返回行数

错误2:JOIN时忘记ON条件

错误示例

SELECT * 
FROM 工单表 w
JOIN 客户表 c;  -- 笛卡尔积!100万 × 10万 = 1000亿行!

正确做法

SELECT * 
FROM 工单表 w
JOIN 客户表 c ON w.客户ID = c.客户ID;  -- 必须指定关联条件

错误3:WHERE和HAVING混淆

错误示例

SELECT 门店ID, COUNT(*) as 工单数
FROM 工单表
WHERE COUNT(*) > 100  -- 错误!WHERE不能用聚合函数
GROUP BY 门店ID;

正确做法

SELECT 门店ID, COUNT(*) as 工单数
FROM 工单表
GROUP BY 门店ID
HAVING COUNT(*) > 100;  -- 用HAVING筛选分组结果

从SQL小白到数据分析高手

Level 1:SQL搬运工

特征

  • 只会SELECT * FROM 表名
  • 需要什么数据都要找技术部帮忙
  • 拿到数据后用Excel分析

Level 2:条件查询者

特征

  • 会用WHERE、AND、OR筛选数据
  • 会用基本的JOIN关联两个表
  • 能独立完成简单的数据提取

Level 3:数据分析师

特征

  • 熟练使用GROUP BY、HAVING做统计分析
  • 能写复杂的多表关联查询
  • 能用子查询解决复杂问题
  • 不再依赖技术部,自己就是自己的"数据工程师"

今日作业

基础练习

  1. 写一个查询,找出你们公司某个门店上个月的所有工单
  2. 加上WHERE条件,筛选出费用超过平均值的工单

进阶挑战

  1. 写一个关联查询,把工单表和客户表连起来,显示客户姓名和维修费用
  2. 用GROUP BY统计每个客户的维修次数

实战应用

  1. 找到你工作中的一个实际问题,尝试用SQL查询来解决
  2. 对比用Excel做和用SQL做,记录时间差

明日预告

Day 11下午:SQL聚合分析实战 - 让数据自己讲出商业洞察

今天你学会了SQL的基础:

  • 查询数据(SELECT)
  • 筛选条件(WHERE)
  • 多表关联(JOIN)

但这只是开始。明天你将学会:

  • 子查询:查询套查询,解决复杂业务问题
  • 窗口函数:在不分组的情况下做排名和对比
  • CASE WHEN:在SQL里写业务逻辑
  • 实战案例:如何用一条SQL生成复杂的分析报表

你会看到:一个运营专家如何用SQL把"数据仓库"变成"商业洞察制造机"。

未经允许不得转载:似水流年 » Day 11上午:SQL基础 - 打开数据宝库的万能钥匙