SQL入门:如何在Count()子查询中使用Max()查询各国最热门文章
问题背景
现有3张业务数据表,字段定义如下:
Customer:存储客户信息,字段为id、name、age、city、countryArticles_read:存储客户阅读文章的行为记录,字段为customer_id、article_id、dateArticle:存储文章基础信息,字段为id、name、author
已初步写出统计每个国家下各文章总阅读量的SQL:
SELECT c.country,a.id,SUM(ar.article_id) AS total_reads FROM customer c JOIN article a ON c.id = a.id JOIN article_reads ar ON c.id = ar.customer_id GROUP BY c.country,a.id ORDER BY total_reads desc;
当前需求为:查询每个国家阅读量最高的文章,仅输出国家、文章名称两个字段。
尝试基于上述统计结果用MAX()取值时持续报错,认为需要结合DISTINCT保证每个国家仅返回1条最高阅读量对应文章,编写的错误SQL如下:
SELECT (DISTINCT c.country),a.id,MAX(ar.article.id) FROM SUM(ar.article_id) AS total_reads FROM customer c JOIN article a ON c.id = a.id JOIN article_reads ar ON c.id = ar.customer_id GROUP BY c.country,a.id ORDER BY total_reads desc;
不需要直接给出最终正确SQL,仅需要实现思路指引。
实现思路指引
- 先修正初始统计SQL的逻辑错误
现有JOIN条件关联逻辑有误:文章表和阅读记录表的关联应该依靠article.id = article_read.article_id,客户表和阅读记录表关联依靠customer.id = article_read.customer_id,当前写的JOIN article a ON c.id = a.id是把客户ID和文章ID做关联,统计出的阅读量数据从根源上就不准确。另外统计阅读量应该用COUNT(ar.article_id),不是SUM(ar.article_id)——SUM是对ID数值做求和,不是统计阅读记录的条数。 - 理清
DISTINCT和分组聚合的适用场景
需求本质是每个国家分组下取最高值对应的记录,DISTINCT仅能做结果去重,无法实现「分组后取组内排序第一的记录」的逻辑,不需要强行添加DISTINCT。 - 拆解需求分步骤实现
- 第一步:先写对基础统计SQL,正确算出「每个国家+每篇文章」对应的总阅读量,把这个结果作为临时结果集(可以用CTE、子查询实现)
- 第二步:针对上述临时结果集,给每个国家内的所有文章按阅读量从高到低做排名,用窗口函数
RANK()或者ROW_NUMBER()都可以,如果允许同阅读量并列第一就用RANK,每个国家只取一条结果就用ROW_NUMBER - 第三步:筛选排名为1的记录,最后关联文章表取出文章名称,只保留要求输出的两个字段即可。
- 可对照排查错误SQL的语法问题
DISTINCT要写在SELECT后面所有字段的最前面,不能加括号单独包裹某一个字段- 不能在FROM后面直接跟聚合函数
SUM(),聚合逻辑要写在SELECT子句或者HAVING子句里 - 字段引用不能写
ar.article.id这种跨表叠写的格式,单张表的字段只能遵循表别名.字段名的格式
内容的提问来源于stack exchange,提问作者Inthemaking
相关产品推荐
相关产品推荐

