SQL GROUP BY报错求助:筛选所属类别全为日本的店铺名称
首先明确你的需求:要找出所有所属类别下全部店铺都位于日本的店铺信息,也就是像Health和Sport这类,类别里没有非日本店铺的那些店铺。
先看你遇到的报错原因:
ERROR: column "t3.country" must appear in the GROUP BY clause or be used in an aggregate function
LINE 3: inner join (select t2.Category, t3.Country
这个报错是PostgreSQL的严格GROUP BY规则导致的(默认开启了only_full_group_by模式):当你用GROUP BY分组时,SELECT列表里的字段要么是GROUP BY里的分组字段,要么是用了聚合函数(比如MAX、MIN、SUM这类)的字段。你的子查询里选了t3.Country,但GROUP BY只有t2.Category,t3.Country既不在分组字段里,也没被聚合函数包裹,数据库不知道该返回这个分组里的哪个Country值,直接报错。
另外你的子查询还有两个隐藏问题:
- 用
from Info t2, Shop t3是交叉连接(笛卡尔积),会把Info和Shop的所有行强行配对,完全不符合表关联的逻辑,应该用JOIN ... ON关联两张表的Name字段。 - 子查询的关联条件
x.Name = t1.Name是错误的,因为你的子查询根本没输出Name字段,输出的是Category和Country,这会导致关联失败。
修复后的正确查询方法
这里给你两种可行的写法,都能实现你的需求:
方法一:用GROUP BY + HAVING筛选符合条件的类别
先找出所有「全部店铺都在日本」的类别,再关联两张表取出这些类别下的所有店铺信息:
SELECT s.Name, s.Country, i.Category FROM Shop s JOIN Info i ON s.Name = i.Name WHERE i.Category IN ( -- 子查询:筛选出所有店铺都位于日本的类别 SELECT i2.Category FROM Info i2 JOIN Shop s2 ON i2.Name = s2.Name GROUP BY i2.Category -- 条件:该类别下所有店铺的Country都是Japan HAVING MAX(s2.Country) = 'Japan' AND MIN(s2.Country) = 'Japan' );
HAVING子句的逻辑是:如果一个类别里的最大Country和最小Country都是Japan,说明这个类别里所有店铺的Country都是Japan(因为没有其他国家的数值干扰)。
方法二:用NOT EXISTS排除有非日本店铺的类别
这种写法逻辑更直观:只要当前店铺的类别里不存在任何非日本的店铺,就保留该店铺:
SELECT s.Name, s.Country, i.Category FROM Shop s JOIN Info i ON s.Name = i.Name WHERE NOT EXISTS ( SELECT 1 FROM Info i2 JOIN Shop s2 ON i2.Name = s2.Name WHERE i2.Category = i.Category AND s2.Country != 'Japan' );
验证结果
执行上面任意一种SQL,都会得到你预期的输出:
| Name | Country | Category |
|---|---|---|
| Pharmacy | Japan | Health |
| Nature Shop | Japan | Health |
| Medical 100 | Japan | Health |
| Sports Life | Japan | Sport |
| Athletics | Japan | Sport |
内容的提问来源于stack exchange,提问作者ceno980

