能否将该MySQL子查询转换为JOIN语句?附目标SQL示例
当然可以转换!而且优化后的JOIN写法更清晰规范
首先先明确你的原查询实际需求:获取每篇新闻的newsId,以及该新闻的最新一条评论(按date降序取第一条),最终按新闻的发布日期倒序排序。原查询里其实有冗余逻辑(比如同时做了隐式JOIN和关联子查询,GROUP BY也显得多余),转换为JOIN写法后可以解决这些问题,这里给你两种常用的实现方式:
方法1:用窗口函数(推荐,逻辑直观)
这种方式利用ROW_NUMBER()窗口函数给每个新闻的评论按日期倒序编号,只保留每个新闻的第一条评论,再和news表关联:
SELECT n.newsId, c.text FROM news n LEFT JOIN ( SELECT newsId, text, -- 按新闻分组,评论日期倒序排,给每条评论编号 ROW_NUMBER() OVER (PARTITION BY newsId ORDER BY date DESC) AS rn FROM comments ) c ON n.newsId = c.newsId AND c.rn = 1 ORDER BY n.date DESC;
- 如果需要只返回有评论的新闻,把
LEFT JOIN换成INNER JOIN即可。 - 窗口函数的写法在MySQL 8.0+、PostgreSQL、SQL Server等主流数据库都支持。
方法2:用自连接找最新评论
如果你用的是不支持窗口函数的旧版数据库(比如MySQL 5.x),可以用自连接的方式找到每条新闻的最新评论:
SELECT n.newsId, c.text FROM news n LEFT JOIN comments c ON n.newsId = c.newsId -- 自连接找比当前评论更新的记录 LEFT JOIN comments c2 ON c.newsId = c2.newsId AND c.date < c2.date -- 没有更新的记录,说明当前评论是最新的 WHERE c2.newsId IS NULL ORDER BY n.date DESC;
原查询的小问题说明
你的原查询里FROM news , comments是隐式JOIN写法(不推荐,可读性差),而且同时JOIN了comments又用关联子查询,其实子查询已经能通过newsId关联到新闻,冗余的JOIN和GROUP BY在严格的SQL模式下(比如MySQL的ONLY_FULL_GROUP_BY)可能会触发语法错误,转换后的写法更符合现代SQL规范。
内容的提问来源于stack exchange,提问作者Danny St.
相关产品推荐
相关产品推荐

