LEFT JOIN 和 INNER JOIN 差在哪?4 种 JOIN 同一份数据跑一遍
6 个用户、8 条订单同一份数据换成四种连表方式结果行数分别是 7、8、8、9。多出来的行不是随便凑的。LEFT JOIN 多的是一个从没下过单的用户RIGHT JOIN 多的是一条查不到用户的订单。在线案例与源码https://atomgit.com/deli007/demo_park/tree/main/codearts-sql-join-visualizer成品只有一个 index.html双击就能用。一、为什么值得做这题天天有人搜但很少有人把四种放一起数搜 left join 和 inner join 的区别前面几页答案长得差不多各给一张结果表再补一句「左表全保留」。看完还是答不上来同一份数据换一种连法到底差在哪几行。所以我把它做成一个页面四种连法压在同一份数据上行数直接可数多出来的行点一下就知道是谁。二、准备环境打开码道 Web把需求写成一段话浏览器打开码道 Web 版https://devcloud.cn-north-4.huaweicloud.com/chat?sourcedmzntgwsfsourceaddmzntgwwbwz 登录后在对话框里写需求就能拿到一个能跑的单文件应用。码道有三种使用方式WebUI浏览器对话、TUI终端命令行和桌面 IDEIDE 插件。本文用 WebUI 版演示。需求我写了 8 条事后看最值钱的是第 4 条和第 5 条。第 4 条要求点结果表任意一行能高亮它的来源组合第 5 条要求顶部一张表同时列出四种连法的结果行数。有了这两条页面就从一张静态结果表变成能自己数、自己点的东西。三、需求原文可以照着复制做一个单文件网页小应用 index.html主题是「SQL JOIN 连表可视化实验室」中文界面全部代码内联在 index.html 里不引用任何 CDN 或外部资源断网也能跑。 要求 1. 内置两份固定示例数据直接写在代码里用户表 users6 行列为 id、name、city其中 1 行的 city 为空订单表 orders8 行列为 id、user_id、amount其中 1 行的 user_id 在 users 表里不存在。 2. 支持切换 4 种连表方式INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN连表条件都是 users.id orders.user_id。 3. 主区域并排显示「左表 users」「右表 orders」「结果表」三块结果表逐行列出连表后的真实记录把 NULL 用醒目的样式标出来。 4. 点结果表里任意一行能在左右表中高亮出这一行是由哪几行组合出来的。 5. 顶部放一张统计表一次列出四种 JOIN 各自的结果行数能一眼看出哪种 JOIN 比 INNER JOIN 多出几行。 6. 内置自检面板页面加载后自动跑一组断言四种 JOIN 的行数、外连接里是否出现 NULL 等显示断言总数与通过数。 7. 提供「自定义数据」输入区可以粘贴自己的两张表CSV 文本后重新计算如果粘贴的文本格式不对列名不匹配、没有数据行用中文明确提示原因并保留上一次的有效结果。 8. 所有计算都在浏览器本地完成不发起任何网络请求。 完成后打开预览让我直接看到运行效果。四、页面长什么样三张表并排点一行就看来源上半部分是连表方式切换按钮和行数对比表下半部分是左表、右表、结果表三块并排。点结果表任意一行左表和右表里对应的行一起高亮底部提示条写出这一行是从哪几行拼出来的。页面用颜色区分四种来源绿色是双方匹配上的黄色是仅左表保留的蓝色是仅右表保留的红色是补位的 NULL。五、同一份数据四种连法就是四个数连表方式结果行数比 INNER JOIN 多多出来的那一行是谁INNER JOIN7基准—LEFT JOIN81用户 David他一条订单都没有RIGHT JOIN81订单 #107它的 user_id 是 7用户表里没有 7 号FULL JOIN92上面两行都在6 乘 8 一共 48 种组合真正匹配上的只有 7 种这就是 INNER JOIN 的 7 行。LEFT JOIN 和 RIGHT JOIN 都是 8 行但多出来的不是同一行这是最容易记混的地方。六、多出来的行一个来自左表一个来自右表David 在用户表里但订单表里没有他的 user_id所以 LEFT JOIN 把他留下来右侧三列补 NULL。订单 #107 是反过来那种它在订单表里但用户表里没有 7 号用户RIGHT JOIN 把它留下来左侧补 NULL。一句话概括谁写在 JOIN 左边就决定补 NULL 往哪边补。七、核心那段代码一次双循环四种连法共用joinTables() 先老老实实穷举所有匹配再用两个标记数组记下谁被匹配过。functionjoinTables(left,right,t){varrows[];varleftMatchednewArray(left.length).fill(false);varrightUsednewArray(right.length).fill(false);varkeysLleft.map(function(r){returnkeyOf(r.id);});varkeysRright.map(function(r){returnkeyOf(r.user_id);});for(vari0;ileft.length;i){for(varj0;jright.length;j){if(keysEqual(keysL[i],keysR[j])){rows.push({li:i,ri:j,left:left[i],right:right[j]});leftMatched[i]true;rightUsed[j]true;}}}if(tLEFT||tFULL){for(i0;ileft.length;i){if(!leftMatched[i])rows.push({li:i,ri:-1,left:left[i],right:null});}}if(tRIGHT||tFULL){for(j0;jright.length;j){if(!rightUsed[j])rows.push({li:-1,ri:j,left:null,right:right[j]});}}returnrows;}四种连法的差别全在后面两段LEFT 补 leftMatched 里没被标记的行RIGHT 补 rightUsed 里没被标记的FULL 两边都补。被匹配过的行记在 leftMatched、rightUsed 里所以补出来的行不会重复。八、验证与踩坑页面加载后会自己跑一遍断言内置数据下是 18/18 通过。原文几条INNER JOIN 行数 独立统计的匹配对数7、LEFT JOIN 行数 INNER 行数 左表未匹配行数1、FULL JOIN 中含 NULL 的行数 左右未匹配总数2。前 12 条是通用关系式换成任何数据都该成立最后 6 条才针对内置数据写死行数。第一个边界是空值用户 Eve 的 city 是空字符串结果表里显示成红色 NULL。也就是说这个页面把空串当 NULL 处理而真实 SQL 里 ‘’ 和 NULL 并不等价。第二个边界是键的比较方式。我拿一版自定义数据试过左表 id 写 ‘01’ 和 ‘1’右表 user_id 写 ‘1’ 和 ‘001’。四种连法都给 4 行因为页面把键归一化成数字再比2 乘 2 全叉乘。真实 SQL 里字符串列的 ‘01’ ‘1’ 是假只有等值的那一对会连上。第三个边界在自检面板上换成自定义数据后它显示 12/13不是 18/18。原因是那条固定期望断言被跳过了但仍然算在分母里。失败路径我也点了一遍往左表文本框里粘一份列数对不上的 CSV。页面给的原话是「users 表 第 3 行列数少于表头表头 3 列该行只有 2 列」后面跟一句「已保留上一次有效结果请修正后重试」。它没白屏也没静默失败结果表里还是上一次的 6 行数据。九、实测数据汇总项目实测值内置左表 users6 行列为 id、name、city内置右表 orders8 行列为 id、user_id、amount四种连法行数7 / 8 / 8 / 9页面自检18/18 通过单个 HTML 体积34959 字符无外链页面网络请求0 条失败提示原文users 表 第 3 行列数少于表头表头 3 列该行只有 2 列最后一行是我用浏览器网络面板复核的打开页面到来回切四种连法请求列表一直是空的。十、本地复现双击 index.html 就能用不需要装任何依赖。想走静态服务python -m http.server 8000 然后访问 http://localhost:8000 。想看它有没有偷偷联网按 F12 打开网络面板再切几次连表方式列表里不会多出请求。十一、说点不足MySQL 8 及以前的版本没有 FULL JOIN页面演示的是 SQL 标准里的语义。真要在 MySQL 里写全连接得用 LEFT JOIN 和 RIGHT JOIN 拼一个 UNION。连接条件只支持单列等值多条件 ON 和不等值连接没做。键会先按数字归一化再比较用字符串主键的场景要留意上面说的那条边界。直接下载试玩这个 Demo 已经完整开源源代码、本文档、全部截图托管在公开仓库可直接下载来玩Demo Park 仓库https://atomgit.com/deli007/demo_park本案例目录https://atomgit.com/deli007/demo_park/tree/main/codearts-sql-join-visualizer打开上面的链接进入 codearts-sql-join-visualizer 文件夹把 index.html 下载到本地用浏览器打开即可运行无需安装任何依赖。十二、用码道做这个页面的体会第一条是需求里要写清验收方式我把「完成后打开预览」固定加在需求末尾省掉了追问的来回。第二条是数字要写进需求行数对比表是我点名要的多出来的行数直接变成页面上的 1、2。第三条是失败路径要单独交代我写了格式错误要给中文原因并保留上一次结果交回来的就是列数不符的提示。第四条是自检这种东西得先想清楚关系式写死数字只能证明这一份数据对关系式才证明引擎没算错。第五条是生成物要自己验四种连法的行数、空值边界、自定义数据的叉乘都是我在浏览器里一条条点出来的。

相关新闻

C++ STL list容器详解:从接口用法到底层实现手写模拟

C++ STL list容器详解:从接口用法到底层实现手写模拟

如果你刷过C算法题或写过相关业务代码,大概率遇到过这种场景:需要在一个大型对象的集合里频繁做头部插入、中间删除,结果用std::vector一跑,数据量一上去立刻卡顿;换std::list之后,插入删除瞬间变得很轻快。…

2026/10/18 8:10:11 阅读更多 →
把ltx-2.5-mlx的62.4GB显存占用砍掉35%:DiT驱逐与文本编码器int8量化双技详解

把ltx-2.5-mlx的62.4GB显存占用砍掉35%:DiT驱逐与文本编码器int8量化双技详解

人工智能基础模型大模型媒体生成本地部署视频 【免费下载链接】ltx-2.5-mlx 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/ltx-2.5-mlx 点击查看 免费下载 🎬 ltx-2.5-mlx 是 Lightricks 22B 音视频联合生成模型 LTX-2.5 的 MLX 格式转换…

2026/10/18 8:09:11 阅读更多 →
Win7 x64 SP1中简优化终极版:系统镜像封装全流程解析

Win7 x64 SP1中简优化终极版:系统镜像封装全流程解析

看到标题里那串数字,常年折腾系统的人应该会心一笑:7601.28117,Win7 x64 SP1。这个版本号放在今天来看,几乎就是一套老系统的毕业照。从XP时代一路折腾过来,我做系统镜像也有些年头了,这次借这版“中简优化…

2026/10/18 8:09:11 阅读更多 →

最新新闻

计算机基础面试:URL全流程、三次握手与HTTP演进要点

计算机基础面试:URL全流程、三次握手与HTTP演进要点

简介:这是一份面向程序员求职与面试准备的计算机网络基础知识点PDF资料,尤其适合准备后端、前端岗位笔试面试的求职者,用于快速补齐高频考点。内容取自代码随想录知识星球精华(最强八股文)第五版计算机基础篇&#xff…

2026/10/18 9:56:37 阅读更多 →
手写BP神经网络逼近二元函数:从零实现前向反向传播

手写BP神经网络逼近二元函数:从零实现前向反向传播

简介:本资源是一份面向机器学习初学者与MATLAB实践者的BP神经网络教学实现,聚焦于不依赖任何工具箱的手动构建与训练过程,重点解决二元函数逼近这一典型非线性拟合问题。压缩包为1KB的ZIP文件,内含1个核心MATLAB源码文件&#xff…

2026/10/18 9:56:36 阅读更多 →
程序员职业倦怠自救指南:7个心态调整法,把能量省下来

程序员职业倦怠自救指南:7个心态调整法,把能量省下来

前阵子和一个做了七八年后端的朋友吃饭,他说了一句话让我印象很深:“我现在不是累,是麻木。写代码没有快感,下班不知道干什么,第二天又坐在工位前发呆。”我听完第一个反应不是安慰他,而是松了一口气——因…

2026/10/18 9:56:36 阅读更多 →
旧房改造,补的是几十年积累的“老化欠账”

旧房改造,补的是几十年积累的“老化欠账”

最近有几个老旧小区的朋友同时问我类似的问题:房子被列入旧房改造名单,到底是好事还是麻烦?要不要趁机把家里重新弄一遍?大部分人的第一反应都是——改造是不是就是刷刷外墙、修修路,做个表面文章,好让小区…

2026/10/18 9:56:36 阅读更多 →
Oracle跨版本SQL执行计划快照集:10g-19c调优实战指南

Oracle跨版本SQL执行计划快照集:10g-19c调优实战指南

简介:本资源是面向Oracle数据库管理员(DBA)与性能调优工程师的SQL Tuning Advisor(SQLT)实战工具集,聚焦10g至19c全版本兼容的SQL性能诊断与优化场景。压缩包内含205个高实用性文件,主体为160个…

2026/10/18 9:56:36 阅读更多 →
基于SpringBoot+Vue的课外活动管理系统设计与实现

基于SpringBoot+Vue的课外活动管理系统设计与实现

1. 项目整体思路与技术选型前后端分离已经是现在做课外活动管理系统的主流姿势,但真正从零开始把分支打全、逻辑理清楚,还是要费不少功夫。这套基于JavaSpringBootVue的课外活动管理系统,核心解决的是高校/中职院校里“活动发布—报名—签到—…

2026/10/18 9:55:36 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →