如何在SQL中将另一表的ID列表作为查询列返回?
用单条SQL实现表a关联表b的ID聚合查询
当然可以!你要的这种把关联表的多行ID合并成逗号分隔字符串的需求,完全可以通过单条SQL完成,不同数据库有各自对应的聚合函数,我给你整理几种常见数据库的实现方式:
MySQL/MariaDB
使用GROUP_CONCAT()函数,这是这类场景下最常用的函数:
SELECT a.id, a.name, GROUP_CONCAT(b.id SEPARATOR ',') AS b_ids FROM a LEFT JOIN b ON a.id = b.a_id GROUP BY a.id, a.name;
这里用LEFT JOIN是为了保证表a的所有数据都能被查询到,哪怕表b里没有对应的关联记录(此时b_ids会是NULL)。
PostgreSQL
PostgreSQL用STRING_AGG()函数:
SELECT a.id, a.name, STRING_AGG(b.id::TEXT, ',') AS b_ids FROM a LEFT JOIN b ON a.id = b.a_id GROUP BY a.id, a.name;
注意需要把b.id转换成TEXT类型,因为STRING_AGG要求聚合的是字符串类型。
SQL Server
SQL Server 2017及以后版本支持STRING_AGG(),写法简洁直观:
SELECT a.id, a.name, STRING_AGG(b.id, ',') AS b_ids FROM a LEFT JOIN b ON a.id = b.a_id GROUP BY a.id, a.name;
如果是更早的版本,需要用FOR XML PATH的方式模拟聚合:
SELECT a.id, a.name, STUFF( (SELECT ',' + CAST(b.id AS VARCHAR) FROM b WHERE b.a_id = a.id FOR XML PATH('')), 1, 1, '' ) AS b_ids FROM a;
STUFF函数的作用是去掉拼接后开头多余的逗号。
Oracle
Oracle用LISTAGG()函数,还能指定聚合后ID的排序顺序:
SELECT a.id, a.name, LISTAGG(b.id, ',') WITHIN GROUP (ORDER BY b.id) AS b_ids FROM a LEFT JOIN b ON a.id = b.a_id GROUP BY a.id, a.name;
核心思路其实很简单:通过聚合函数(或模拟聚合的方式)将关联表b中匹配的id值合并成单个字符串,同时通过LEFT JOIN确保表a的所有行都能被返回,不会因为没有关联记录而被过滤掉。
内容的提问来源于stack exchange,提问作者Lars Kakavandi-Nielsen
相关产品推荐
相关产品推荐

