为什么学SQL
数据分析师70%的时间花在取数上,SQL就是取数的语言。学会SQL,你可以直接从数据库里拿到想要的数据,不用等别人导出。本教程用一张电商订单表贯穿全程,逐层讲解,每层都给可直接套用的模板。
第一层:SELECT基础与WHERE过滤
假设有订单表 orders:order_id, user_id, amount, status, create_time。取全部订单:SELECT * FROM orders;。只取需要的列:SELECT order_id, amount FROM orders;。
WHERE 过滤是日常最高频的操作:已支付订单:SELECT * FROM orders WHERE status=paid;。金额大于500的:SELECT * FROM orders WHERE amount>500;。多条件:WHERE status=paid AND amount>500(且)、OR(或)、IN (paid, refunded)(在集合中)、LIKE 手机%(模糊匹配)。
实用模板:取最近7天的订单:WHERE create_time >= DATE(now, -7 day)(SQLite语法;MySQL用 DATE_SUB(NOW(), INTERVAL 7 DAY))。
第二层:聚合与GROUP BY
统计每天订单数:SELECT DATE(create_time) AS day, COUNT(*) AS order_cnt FROM orders GROUP BY DATE(create_time);。按状态统计:SELECT status, COUNT(*), SUM(amount) FROM orders GROUP BY status;。
聚合函数速查:COUNT(*)行数、SUM(amount)求和、AVG(amount)平均、MAX/MIN最大最小、COUNT(DISTINCT user_id)去重用户数。HAVING 用于过滤聚合结果:只保留订单数大于100的日期:GROUP BY … HAVING COUNT(*)>100。
模板:每日销售额与订单数:SELECT DATE(create_time), COUNT(*), SUM(amount) FROM orders WHERE status=paid GROUP BY DATE(create_time) ORDER BY DATE(create_time);。
第三层:JOIN关联查询
业务数据分散在多张表:订单表只有 user_id,用户信息在 users 表。内连接取交集:SELECT o.order_id, u.user_name, o.amount FROM orders o JOIN users u ON o.user_id = u.user_id;。
LEFT JOIN 保留左表全部(查没下过单的用户):SELECT u.user_id, COUNT(o.order_id) FROM users u LEFT JOIN orders o ON u.user_id=o.user_id GROUP BY u.user_id HAVING COUNT(o.order_id)=0;。
常见坑:JOIN 后行数变多,因为一对多关联会把数据复制;关联条件写错会产生笛卡尔积爆炸。记住:JOIN 前先看每张表的粒度。
第四层:窗口函数
窗口函数解决排名、累计、环比这类需要跨行计算的问题。每用户首单时间:SELECT user_id, order_id, create_time, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY create_time) AS rn FROM orders;,rn=1 的就是首单。
每日环比:用 LAG 取前一天值:SELECT day, amount, LAG(amount) OVER (ORDER BY day) AS prev_amount FROM daily_sales;。窗口函数比自关联快得多,是进阶必学。
实战:一个完整取数需求
需求:近30天,每个城市、每个品类的付费订单金额和订单数,只保留金额大于10000的组合,按金额降序。SQL:SELECT u.city, p.category, COUNT(o.order_id) AS cnt, SUM(o.amount) AS amt FROM orders o JOIN users u ON o.user_id=u.user_id JOIN products p ON o.product_id=p.product_id WHERE o.status=paid AND o.create_time>=DATE(now, -30 day) GROUP BY u.city, p.category HAVING amt>10000 ORDER BY amt DESC;。把这段当模板,换成自己的表名和字段即可。
练习建议
SQL只能靠练。推荐 sqlzoo.net(免费中文练习题,从SELECT到JOIN全覆盖),每天20分钟,一周就能上手日常取数。练完再拿公司真实数据(只读权限)练手,两周后你就不再需要求人取数了。