惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
aimingoo的专栏
aimingoo的专栏
F
Fortinet All Blogs
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
MongoDB | Blog
MongoDB | Blog
月光博客
月光博客
The Cloudflare Blog
量子位
T
Tailwind CSS Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog
MyScale Blog
MyScale Blog
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
G
Google Developers Blog
D
DataBreaches.Net
V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
U
Unit 42
博客园 - 聂微东
有赞技术团队
有赞技术团队
A
About on SuperTechFans

Hsu Yeung 的博客

三圣花市 | Hsu Yeung 的博客 网站支持 Live Photo 图片展示 | Hsu Yeung 的博客 梦 | Hsu Yeung 的博客 周末午餐 | Hsu Yeung 的博客 张家界 | Hsu Yeung 的博客 话剧《寻她芳踪·张爱玲》 | Hsu Yeung 的博客 博客自动生成文章目录 | Hsu Yeung 的博客 灭螂行动! | Hsu Yeung 的博客 张靓颖成都演唱会 | Hsu Yeung 的博客 最近对博客做的一些微调总结 | Hsu Yeung 的博客 Windows 上安装 Lua | Hsu Yeung 的博客 网站支持展示 B 站 iframe 视频 SpringBoot 中使用 RedisTemplate 存取整数值的坑 | Hsu Yeung 的博客 值得记录的一些工作近况 | Hsu Yeung 的博客 周传雄成都演唱会 | Hsu Yeung 的博客 并行操作导致获取数据库连接超时 | Hsu Yeung 的博客 风信子 | Hsu Yeung 的博客 Linux 安装并配置 Nginx | Hsu Yeung 的博客 使用 logrotate 切割 nginx 日志 郁金香土培结果 | Hsu Yeung 的博客 MySQL LEFT JOIN 右表有多条数据但只取最新的一条 | Hsu Yeung 的博客 获取数据库锁等待超时问题 | Hsu Yeung 的博客 从零开始挑选相机 | Hsu Yeung 的博客 郁金香 | Hsu Yeung 的博客 我的第一束花 | Hsu Yeung 的博客 快乐的一周 | Hsu Yeung 的博客 重庆,来了 | Hsu Yeung 的博客 散步 | Hsu Yeung 的博客 Git 工作区、暂存区、版本库之间的关系 | Hsu Yeung 的博客 Collectors.toMap() 操作 value 为 null 的情况
SQL JOIN 中 ON 与 WHERE 的区别
2024-10-11 · via Hsu Yeung 的博客

前两周写一条查询语句时不小心踩了一个比较初级的坑,这里用博客的文章表和内容表来举例,文章表中有个 content_id 字段,对应的是内容表的主键 id。需求是需要查询出所有未被删除的文章列表并且查出对应文章的内容,文章内容允许为空。

第一印象就很容想到以文章表为主表然后去外连接内容表进行关联查询,这里先给出正确的 SQL:

SELECT
    t1.id,
    t1.title,
    t2.html_content AS content 
FROM
    t_article AS t1
    LEFT JOIN t_content AS t2 ON t2.id = t1.content_id 
    AND t2.is_deleted = 0 
WHERE
    t1.is_deleted = 0
正确的查询结果
正确的查询结果

可以看出是查出来了四条数据,并且第四条数据的文章内容是空的,符合要求。

再看当时写的错误的 SQL:

SELECT
    t1.id,
    t1.title,
    t2.html_content AS content 
FROM
    t_article AS t1
    LEFT JOIN t_content AS t2 ON t2.id = t1.content_id 
WHERE
    t1.is_deleted = 0
AND t2.is_deleted = 0
错误的 SQL
错误的 SQL

发现这里查出来的数据少了一条,区别就在于 t2.is_deleted 这个过滤条件从 LEFT JOIN ... ON 的后面给放到了 WHERE 后面。

再看另外一种和上面错误 SQL 等效的写法:

SELECT
    t1.id,
    t1.title,
    t2.html_content AS content 
FROM
    t_article AS t1
    INNER JOIN t_content AS t2 ON t2.id = t1.content_id AND t2.is_deleted = 0
WHERE
    t1.is_deleted = 0
错误 SQL 的等效 SQL
错误 SQL 的等效 SQL

这里查出来的数据也是只有三条,内容为 null 的那一条数据没有被查出来。

其实这是因为当关联条件放到 LEFT JOIN ... ON 后面的时候是会先将右表的数据过滤然后再与左表进行关联,放到 WHERE 后面的话实际上前面的 LEFT JOIN 就相当于 INNER JOIN 了,会先关联产生临时表数据再进行筛选。由于id 为 34 的那篇文章的内容对应的数据表的 is_deleted 字段值为 1,不满足 WHERE 条件,所以这条数据就不会被查询出来。

所以说,联表查询数据的时候,要分清楚最终结果集以谁的数据为准,再考虑用什么连接方式以及过滤条件该写在哪个位置,这些都是需要注意的。