资讯详情

资讯详情

零基础学SQL:从SELECT到JOIN的查询入门与避坑指南

简介这份 PDF 笔记源自 B 站 Mosh 老师三小时 SQL 入门课程面向零基础学习者以及需要快速查漏补缺的开发者用一册浓缩文档解决语法记不牢、知识点零散的问题。全包仅 1 个 PDF 文件约 2.43MB体积轻巧打印成纸质速查表或放在手边对照练习都很方便。笔记按课程脉络编排从数据库与 SQL 基础概念讲起依次覆盖 SELECT 子句、WHERE 条件、逻辑运算符以及 IN、BETWEEN、LIKE、REGEXP、IS NULL 等常用筛选写法并延伸到 ORDER BY 排序、LIMIT 限制、内连接与外连接、USING 子句、交叉连接、UNION 合并结果集和插入数据等主题每个知识点都配有可直接套用的语法模板便于边看边写、随查随用。目前已有 983 人学习适合作为入门阶段的复习提纲与日常编写 SQL 的随手参考。1. 零基础学 SQL先弄明白它到底在干什么很多人第一次听到 SQL脑子里冒出的画面是一堆黑色终端、满屏大写英文然后本能地觉得自己学不会。我第一次接触时也这样想直到有人跟我说了一句大白话SQL 就是你跟表格说话的语言。你手上有一张 Excel 客户表想让电脑“把北京地区积分超过 1000 的人按名字排好序只给我看前 3 个”这句话你用中文说电脑听不懂你用 SQL 说它秒懂。所以 SQL 全称 Structured Query Language中文叫结构化查询语言本质是一套向数据库要数据的固定句式。数据库你可以理解成一个超级能装的表格柜SQL 就是打开柜子、翻找、筛选、排序的那把钥匙。它不挑行业做运营要看数据、做产品要拉报表、做开发要存取数据都绕不开它。这份 Mosh 老师三小时课程的笔记价值就在于把新手最该先掌握的那批句式按“查、筛、排、连、插”的顺序串成了一条能直接照抄的路线。入门阶段不需要懂数据库内核能把自己的问题翻译成一句 SQL就已经跨过门槛了。2. 为什么新手第一门该学 SQL投入小、见效快、通用性强2.1 它是最不像编程的编程技能学一门编程语言通常要先装环境、配依赖、理解变量类型和函数调用折腾半天才能打印出一行字。SQL 不一样它没有复杂的语法结构核心句式加起来也就十来个关键词写出来接近英语口语SELECT 什么 FROM 哪张表 WHERE 什么条件。你甚至可以先不装任何软件用一个在线的练习库把基本句式跑一遍十分钟就能看到结果。这带来的心理优势非常大。零基础的人最怕的是“学了两周还看不到东西”而 SQL 是学一小时就能查出真实数据的技术。我个人觉得这种即时反馈对坚持学习的帮助比任何学习方法都管用。2.2 一次学会到处能用SQL 是一个标准MySQL、PostgreSQL、SQL Server、Oracle 这些主流数据库都支持同一套核心语法。这份笔记里用的示例库是 MySQL 风格语句结尾要加分号但你把同样的 SELECT、WHERE、ORDER BY 搬到别的数据库里八成以上能直接跑。这意味着你学的不是某个软件的按钮位置而是一项可以带走的通用能力。换公司、换项目、换数据库核心那部分知识不用重学只需要补一点各家的小差异。对新手来说先抓住通用核心比一上来就纠结选哪个数据库重要得多。2.3 它是数据分析方向的第一块垫脚石现在很多岗位的招聘要求里都写着“熟悉 SQL 优先”包括数据分析、产品运营、测试、后端开发。原因很实在数据都存在数据库里不会 SQL 就只能等别人帮你导 Excel会 SQL 就能自己去拿。很多新手会问那我是不是得先学 Python 或者先学统计学入门的话建议反过来。SQL 是取数环节Python 是处理环节统计学是解释环节。取数这一步最简单、最快见效而且不管后面走哪条路都用得上。先把数据拿到手你才有后面的事可做。2.4 三小时能学到什么程度得先把预期放正三小时学不完 SQL但足够让你从“完全不会”变成“能独立写出常见的查询”。这份笔记覆盖的知识点大致是这样一个范围模块包含内容入门后的能力基础查询SELECT、AS 别名、DISTINCT 去重能取出指定列并命名条件筛选WHERE、比较运算符、AND/OR/NOT能按单条件或多条件过滤范围与集合IN、BETWEEN能匹配列表和区间模糊匹配LIKE、REGEXP能按开头、结尾、包含查找空值判断IS NULL能找出缺失数据排序分页ORDER BY、LIMIT能排序并只取前几条多表关联INNER JOIN、LEFT JOIN、USING、CROSS JOIN能把两张表拼起来看结果合并UNION能合并多个查询结果写入数据INSERT INTO能往表里加记录看清楚这张表你会发现它没有涉及索引优化、事务、存储过程这些进阶话题笔记本身也明确说了这只是核心语言构造不是全部。但这已经够你应付日常工作里八成的取数需求这就是它作为入门材料的合理定位。3. 第一个例子怎么跑从一张客户表开始3.1 先搞清楚“表、行、列”这三个词在写任何 SQL 之前脑子里要有一个具体画面。假设有一张叫 customers 的表就是一张客户清单表table整张清单比如 customers列column清单里的每一栏比如 first_name名、state省份、points积分、phone电话行row清单里的每一条记录也就是一个具体客户SQL 干的事就是从这张清单里挑出你要的列和行。挑列用 SELECT挑行用 WHERE就这么简单。这个映射关系一旦建立后面所有关键词都好理解了。3.2 安装与准备新手最省事的两条路第一条路是本地装 MySQL好处是数据在自己电脑上随便折腾。去官网下载安装包安装时记住你设置的 root 密码装完打开命令行客户端或者图形化工具输入密码就能进。这条路稍微花点时间但一劳永逸。第二条路是直接用在线的 SQL 练习环境浏览器打开就能写不用装任何东西。适合先感受一下语法确认自己有兴趣再回头装本地环境。提示新手阶段不要纠结版本号和安装细节能连上、能执行一条 SELECT 就算成功。装不上就先用在线环境别卡在第一步消耗热情。笔记里的示例用的是一个叫 sql_store 的示例库里面预置了 customers、orders 这些表。你自己练习时如果没有这些表可以自己建一张简化版-- 建一张最简单的客户表只保留入门要用的列 CREATE TABLE customers ( customer_id INT PRIMARY KEY, -- 客户编号主键唯一 first_name VARCHAR(50), -- 名 state VARCHAR(10), -- 省份缩写 points INT, -- 积分 phone VARCHAR(20) -- 电话可能为空 ); -- 插入几条测试数据 INSERT INTO customers (customer_id, first_name, state, points, phone) VALUES (1, Mosh, CA, 1200, NULL), (2, Bob, NY, 800, 1234), (3, Alice, VA, 1500, 5678), (4, ben, CA, 300, NULL), (5, Cindy, CA, 950, 9012);这段代码做了两件事CREATE TABLE 定义表结构每个字段后面跟类型INT 是整数VARCHAR(50) 是最多 50 个字符的文本INSERT INTO 往里塞了 5 条假数据其中两条 phone 故意写成 NULL后面演示空值判断时会用到。执行完这两段你的练习环境就搭好了。3.3 第一条真正意义上的查询现在写你的第一句 SQL-- 从 customers 表里取出所有列的所有行 SELECT * FROM customers;*是通配符意思是“所有列”。这条语句没有任何筛选等于把整张表原样打印出来。看起来没什么用但它是你确认“我确实连上数据库了”的第一步。下一步把*换成具体列名-- 只取名字和积分两列 SELECT first_name, points FROM customers;列的顺序由你决定写在前面的先显示。这就是 SELECT 语句的本质控制你要看哪几栏。3.4 加个别名让结果看得懂真实工作里列名经常是英文缩写或者带下划线直接看很费劲。AS 就是给列改个显示名-- 给列起别名并演示表达式计算 SELECT first_name, points, (points * 10 20) AS discount_factor -- 积分换算成一个折扣系数 FROM customers;这里有两个新东西。一是 AS 别名只影响结果的显示名不改数据库里的真实列名。二是 SELECT 后面可以直接写算式points * 10 20会逐行计算。计算顺序遵循普通数学规则先括号再乘除最后加减。这个特性在算比例、算金额时特别常用也是新手容易忽略的一个实用点。3.5 去重结果里为什么老有重复查省份的时候你会发现CA 出现了三次-- 不写 DISTINCT会得到重复的省份 SELECT state FROM customers; -- 加上 DISTINCT每个省份只出现一次 SELECT DISTINCT state FROM customers;DISTINCT 作用于它后面的所有列。如果你写SELECT DISTINCT state, first_name那去重的判断标准就变成“省份和名字的组合”因为名字都不同结果反而一条都不会被去掉。这个坑我踩过当时还以为 DISTINCT 失效了。4. 筛出你要的数据WHERE 和它的几个好搭档4.1 WHERE 是所有查询的分水岭不带 WHERE 的查询是“全都要”带 WHERE 才是“只要我关心的”。这也是新手最该先练熟的一块因为实际工作中九成的查询都带条件。-- 只要 CA 省的客户 SELECT * FROM customers WHERE state CA;文本要用单引号括起来数字不用。这里有个细节SQL 不区分大小写select和SELECT一样能跑WHERE state ca在多数默认配置下也能匹配到 CA。但表里存的数据大小写是敏感的这会导致后面 LIKE 查询出意外第四节会细说。比较运算符一共六个可以当成一张随身卡片运算符含义例子大于points 1000大于等于points 1000小于points 500小于等于points 500等于state CA或!不等于state CA不等于有两种写法和!效果一样遇到哪个都别慌。4.2 多条件组合AND、OR、NOT单个条件不够用时就用逻辑运算符把它们串起来-- AND两个条件都要满足 SELECT * FROM customers WHERE points 800 AND state CA; -- OR满足一个就行 SELECT * FROM customers WHERE state CA OR state NY; -- NOT把条件反过来 SELECT * FROM customers WHERE NOT (state CA);AND 和 OR 混用时AND 的优先级高于 OR这点跟数学里的乘除优先类似。所以WHERE state CA OR state NY AND points 1000实际会被理解成“CA 的全部或者 NY 里积分大于 1000 的”多半不是你想要的。养成加括号的习惯WHERE (state CA OR state NY) AND points 1000才是“CA 或 NY 里积分大于 1000 的”。这是血泪经验逻辑错了结果看起来还挺正常很难发现。4.3 IN 和 BETWEEN少写一堆 OR当条件是“在几个值里面挑”用 IN 比一串 OR 清爽得多-- 只要 VA、NY、CA 这三个省的客户 SELECT * FROM customers WHERE state IN (VA, NY, CA);BETWEEN 处理区间注意它是闭区间两头都包含-- 积分在 100 到 200 之间的客户含 100 和 200 SELECT * FROM customers WHERE points BETWEEN 100 AND 200;新手常犯的错是把 BETWEEN 当成“大于小值、小于大值”结果边界那一条被漏掉或多算。另外BETWEEN 用在日期上时如果字段带时分秒写BETWEEN 2024-01-01 AND 2024-01-31可能漏掉 31 号当天有时分秒的记录这时候要么写到2024-01-31 23:59:59要么改用和组合。4.4 LIKE 与 REGEXP按“模样”找数据不知道完整值、只知道一部分的时候用 LIKE-- 名字以 b 开头的客户 SELECT * FROM customers WHERE first_name LIKE b%; -- 名字正好四个字符的客户 SELECT * FROM customers WHERE first_name LIKE ____;两个通配符要记牢%代表任意多个字符包括零个_代表正好一个字符。b%是以 b 开头%b是以 b 结尾%b%是包含 b。REGEXP 更强支持正则-- 以 a 开头 SELECT * FROM customers WHERE first_name REGEXP ^a; -- 以 ey 或 on 结尾 SELECT * FROM customers WHERE first_name REGEXP ey$|on$; -- 以 my 开头或者包含 se SELECT * FROM customers WHERE first_name REGEXP ^my|se; -- 包含 b且 b 后面跟的是 r 或 u SELECT * FROM customers WHERE first_name REGEXP b[ru];几个符号的意思^是字符串开头$是结尾|是或者[abc]是括号里任意一个字符[a-d]是 a 到 d 的任意一个。这套符号在别的地方也通用学一次能迁移。4.5 IS NULL空白不是零也不是空字符串这是新手最容易翻车的地方。表里 phone 有两行是 NULL你想找出“没填电话的客户”如果写成WHERE phone NULL结果会是空的。因为 NULL 表示“未知”未知和任何值比较都不成立。正确写法只有一个-- 找出没有电话的客户 SELECT * FROM customers WHERE phone IS NULL; -- 反过来找出有电话的客户 SELECT * FROM customers WHERE phone IS NOT NULL;顺便区分三个东西NULL 是没填是填了但内容为空0是一个数字。判断 NULL 只能用 IS NULL 或 IS NOT NULL不能用等号。4.6 ORDER BY 和 LIMIT排序与只取前几条-- 先按省份升序同省再按名字降序 SELECT * FROM customers ORDER BY state ASC, first_name DESC; -- 只要前 3 条 SELECT * FROM customers ORDER BY points DESC LIMIT 3; -- 跳过前 6 条再取 3 条 SELECT * FROM customers LIMIT 6, 3;ASC 是升序可以省略DESC 是降序必须写。LIMIT 的两个参数是“跳过几条, 取几条”LIMIT 6, 3就是跳过 6 条取 3 条做分页时就是这个逻辑。注意 LIMIT 一定要配 ORDER BY 用不然“前 3 条”是按数据库内部顺序取的每次跑出来可能都不一样这个玄学问题排查起来相当费劲。5. 把两张表拼起来看JOIN 入门与数据写入5.1 为什么需要 JOIN真实的数据不会都堆在一张表里。客户信息在 customers订单信息在 orders两张表通过 customer_id 关联。你想看“每个客户的名字和他下的订单金额”就必须把两张表拼起来这个动作就叫 JOIN。-- 内连接只保留两张表都能对上的记录 SELECT * FROM customers c JOIN orders o ON c.customer_id o.customer_id;c和o是表的别名写起来短。ON 后面是连接条件两张表的 customer_id 相等才拼成一行。内连接的特点是没有下过订单的客户不会出现在结果里因为他在 orders 表里找不到匹配。5.2 左连接谁都不能少如果你要“所有客户都列出来下过单的显示订单没下过单的订单字段留空”就得用左连接-- 左连接保留左表全部记录 SELECT * FROM customers c LEFT JOIN orders o ON c.customer_id o.customer_id;左表是 customers它的每一条都会保留右表 orders 没有匹配的地方就填 NULL。判断“哪些客户从没下过单”就是在这个结果上加一句WHERE o.customer_id IS NULL这是个非常实用的套路。5.3 USING 和 CROSS JOIN两个特殊场景如果两张表用来连接的列名完全一样ON 可以简化成 USING-- 列名相同时的简写 SELECT * FROM customers c JOIN orders o USING (customer_id);CROSS JOIN 是笛卡尔积把左表每一行和右表每一行都组合一次。听起来抽象实际场景是“所有颜色配所有尺码”-- 颜色和尺码的所有组合 SELECT * FROM colors CROSS JOIN sizes;三行颜色、四行尺码结果就是十二行。新手误用 CROSS JOIN 会导致结果行数爆炸两张一千行的表叉乘就是一百万行查的时候卡住了先看看是不是漏写了 ON。5.4 UNION把两个结果上下接起来JOIN 是左右拼UNION 是上下接-- 把客户和另一批人的名字、地址合成一个结果 SELECT name, address FROM customers UNION SELECT name, address FROM clients;UNION 要求两边的列数和类型对得上而且它会自动去重。想保留重复就用 UNION ALL。5.5 INSERT往表里加数据-- 插入一条 INSERT INTO customers (first_name, phone, points) VALUES (Mosh, NULL, DEFAULT); -- 一次插入多条 INSERT INTO customers (first_name, phone, points) VALUES (Mosh, NULL, DEFAULT), (Bob, 1234, 10);列名要写全值按照列名的顺序一一对应。DEFAULT 表示用这个字段的默认值。如果某列允许为空你又暂时没值就写 NULL别写成空字符串两者含义不同。6. 新手最容易踩的五个坑排查清单6.1 语句跑不通报语法错误现象一执行就红字报错提示 near 某个词。原因最常见的是漏了分号。MySQL 要求每条语句以分号结尾尤其是命令行里没分号它以为你还没写完。其次是引号用错字符串必须用单引号双引号在部分配置下会被当成列名。解决先检查句尾分号再检查引号配对最后把语句精简到SELECT * FROM 表名 LIMIT 1看能不能跑通再一段段加回去定位。6.2 JOIN 之后结果行数变多了现象两张表各 10 条连接完变成 50 条。原因连接条件不是唯一的。如果 orders 表里一个客户有多条订单那这个客户在结果里就会出现多次这是正常的。但如果你的 customer_id 在右表本应唯一却出现多条就要查数据本身有没有重复。另一种可能是漏写了 ON退化成笛卡尔积。解决先用SELECT COUNT(*)看两边行数再单独查右表的关联列有没有重复值GROUP BY 关联列 HAVING COUNT(*) 1能快速揪出来。6.3 用等号判断 NULL结果永远为空现象WHERE phone NULL查不出任何数据。原因NULL 代表未知未知和任何值比较都不成立包括它自己。解决一律改用IS NULL或IS NOT NULL。这个错误不报错只是默默返回空结果最容易被忽略。6.4 大小写和空格导致的漏查现象表里明明有 Ben用LIKE b%却查不到。原因LIKE 的匹配是否区分大小写取决于数据库和字段的排序规则配置不同环境表现不一样。另外数据里可能有多余空格Ben 和Ben在精确匹配时对不上。解决需要稳定匹配时统一转成小写再比比如WHERE LOWER(first_name) LIKE b%数据有空格就先用 TRIM 处理。别指望环境一致写成显式的才靠谱。6.5 LIMIT 不配 ORDER BY每次结果不一样现象同样一句SELECT * FROM customers LIMIT 3跑两次出来的三条不同。原因没有排序时数据库返回的顺序是不保证的它按自己最方便的方式取。解决只要用到 LIMIT前面一定加 ORDER BY哪怕按主键排也行。这个后悔药事后补很麻烦因为依赖这个结果的代码可能已经上线了。7. 学完这份笔记之后下一步该练什么三小时的内容过完你手上已经有了一套能用的工具箱。接下来的关键不是继续看教程而是把工具用出肌肉记忆。我给新手的路径建议是这样的第一步把第 3 节那张自己建的 customers 表扩充到二三十行故意造一些脏数据——重复的名字、空的电话、大小写混杂的省份。然后给自己出题查出积分最高的三个人、查出没有电话且积分大于 500 的客户、查出每个省有多少人。前两个用 WHERE 和 ORDER BY 就能解第三个需要 GROUP BY 和 COUNT这是你该主动去补的下一个知识点笔记里没有覆盖但它是从“会查”到“会统计”的必经一步。第二步练多表。再建一张 orders 表塞进几十条订单让有些客户有订单、有些没有。然后把内连接、左连接各写五遍重点练“找出没下过单的客户”这种反向查找。JOIN 是新手到进阶之间最大的一道坎光看懂不够得写到不用想就能写出来。第三步养成两个习惯。一是任何查询先写SELECT *加LIMIT 10看一眼数据长什么样再动手改二是所有涉及 NULL 和 LIMIT 的地方写完自己念一遍“这里会不会有坑”。阶段目标建议投入第一周把 WHERE、ORDER BY、LIMIT 写熟每天 3 到 5 道自测题第二周掌握 JOIN 的三种形态每天手写 2 个多表查询第三周补 GROUP BY 与聚合函数做一份按维度汇总的报表之后了解子查询与索引概念遇到慢查询再回头学我第一次学 SQL 的时候卡在 JOIN 上整整两天原因不是不懂语法而是没搞清楚“一对多”会让结果变多。后来我给自己定了个规矩每次写完带 JOIN 的语句先单独查一遍右表的关联列有没有重复值再往下写。这个动作救过我很多次也让排查速度快了不止一倍。不用急着买课也不用追求把 SQL 学全。先把这份笔记里的十来个关键词练到闭着眼能写你就已经比大多数停留在“想学”阶段的人走得远了。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →