SQL中IN子查询返回列数能否多于左侧匹配列?附MAX函数疑问
SQL常见问题解答
问题1:IN子句左侧匹配列数能否少于子查询返回的列数?
不支持这种写法,标准SQL以及绝大多数主流数据库(如MySQL、PostgreSQL、SQL Server)都会直接报错——IN子句要求左右两侧的列数必须完全一致,否则不符合语法规则。
你给出的示例中,左侧是单个street列,但子查询返回street和country两列,这种列数不匹配的情况会触发语法错误。如果需求是匹配street列,只需修改子查询让它仅返回street列即可:
SELECT ... FROM ... WHERE street IN ( SELECT street FROM ... WHERE ... );
如果需要同时匹配street和country两个字段,则要使用行构造器让两侧列数对应:
SELECT ... FROM ... WHERE (street, country) IN ( SELECT street, country FROM ... WHERE ... );
问题2:WHERE子句中能否使用MAX()聚合函数?原写法是否可行?
关于WHERE子句使用聚合函数
不能直接在WHERE子句里使用MAX()这类聚合函数。因为WHERE的作用是筛选原始行数据,而聚合函数是基于分组后的结果计算的,逻辑上WHERE执行时分组还未完成,所以无法直接调用聚合函数。如果要过滤分组后的结果,应该使用HAVING子句,但HAVING仅能针对分组后的聚合结果筛选,无法用来定位单条行数据。
原写法的问题
你给出的查询存在多个语法和逻辑问题:
WHERE MAX(data.number)本身语法无效,WHERE子句需要布尔条件(含比较/逻辑判断),这里既无运算符也无判断逻辑,完全不成立;- 标准SQL中,SELECT子句里的列若不在GROUP BY中,必须被聚合函数包裹(你的
person列既不在GROUP BY,也无聚合处理,仅MySQL宽松模式可能允许,但结果完全不可控); - 即便语法通过,也无法保证拿到每个城市中
number最大的person——GROUP BY city后,person会随机取分组内的某一条数据。
正确实现方式
要获取每个城市中number最大的person和city,推荐使用窗口函数(主流数据库均支持):
SELECT person, city FROM ( SELECT person, city, ROW_NUMBER() OVER (PARTITION BY city ORDER BY number DESC) AS rn FROM data ) t WHERE rn = 1;
也可以用关联子查询先找到每个城市的最大number,再匹配对应行:
SELECT d.person, d.city FROM data d WHERE d.number = ( SELECT MAX(number) FROM data WHERE city = d.city );
内容的提问来源于stack exchange,提问作者Eduardo Marinho
相关产品推荐
相关产品推荐

