PostgreSQL关联多表聚合地址字符串的SQL查询问题
获取学生在校及大学阶段去过的地点(PostgreSQL)
表结构与需求
现有数据库表及数据如下:
Student表
| Id | Name |
|---|---|
| 1 | Roger |
| 2 | Roman |
School表
| Id | Name | Address_Id | Student_Id |
|---|---|---|---|
| 1 | School1 | 1 | 1 |
| 2 | School2 | 2 | 1 |
| 3 | School3 | 3 | 2 |
College表
| Id | Name | Address_Id | Student_Id |
|---|---|---|---|
| 1 | College1 | 1 | 1 |
| 2 | College2 | 3 | 2 |
Address表
| Id | Name |
|---|---|
| 1 | Brooklyn |
| 2 | Manhattan |
| 3 | Troy |
需要查询出学生ID、姓名,以及他们在学校和大学阶段去过的所有地点(去重后用逗号分隔),期望结果:
| ID | Student Name | Visited Places |
|---|---|---|
| 1 | Roger | Brooklyn, Manhattan |
| 2 | Roman | Troy |
原SQL无法运行:
SELECT s.Id AS 'ID', s.Name AS 'Student Name', STRING_AGG(a.Name, ', ')AS 'Visited Places' FROM Student s LEFT JOIN School sc ON sc.Student_Id = s.Id LEFT JOIN Address a ON a.Id = sc.Address_Id LEFT JOIN College c ON c.Student_Id = s.Id LEFT JOIN Address a ON a.Id = c.Address_Id;
问题分析
- 重复使用了别名
a关联Address表,PostgreSQL不允许同一查询中重复定义相同别名 - 未对重复地点去重,比如Roger的Brooklyn在学校和大学都存在,会被重复统计
- 缺少
GROUP BY子句,使用聚合函数STRING_AGG时必须按非聚合字段分组
正确查询语句
SELECT s.Id AS "ID", s.Name AS "Student Name", STRING_AGG(DISTINCT a.Name, ', ') AS "Visited Places" FROM Student s LEFT JOIN ( -- 合并学校和大学的学生-地址关联记录,自动去重重复条目 SELECT Student_Id, Address_Id FROM School UNION SELECT Student_Id, Address_Id FROM College ) AS sc_c ON sc_c.Student_Id = s.Id LEFT JOIN Address a ON a.Id = sc_c.Address_Id GROUP BY s.Id, s.Name;
说明
- 用
UNION合并School和College表的学生地址关联数据,UNION会自动去除重复的(Student_Id, Address_Id)组合 - 使用
DISTINCT确保聚合时每个地点只出现一次,避免同一地点多次显示 - 添加
GROUP BY s.Id, s.Name满足聚合函数的分组要求,确保每个学生对应一条结果
内容的提问来源于stack exchange,提问作者Ricky Vikram
相关产品推荐
相关产品推荐

