技术问询:能否在SELECT查询的列中返回表或子查询数据?
你说的这种需求完全可行,而且确实在生成嵌套JSON时超级实用——不用在应用层做多次查询再拼接,直接用SQL就能把关联数据嵌套成一个字段返回。不过具体实现得看你用的数据库,不同系统的语法略有差异,我给你分几种常见情况说说:
1. PostgreSQL
PostgreSQL对JSON的支持非常友好,用json_agg(或jsonb_agg)配合row_to_json就能轻松实现:
SELECT orderid, date, -- 把关联的orderitems行转成JSON数组 (SELECT json_agg(row_to_json(orderitems)) FROM orderitems WHERE orderid = orders.orderid) AS orderitems FROM orders;
如果你想更简洁,也可以用JOIN加GROUP BY的写法:
SELECT o.orderid, o.date, json_agg(oi) AS orderitems FROM orders o LEFT JOIN orderitems oi ON o.orderid = oi.orderid GROUP BY o.orderid, o.date;
这样返回的orderitems字段就是一个包含所有对应商品的JSON数组。
2. MySQL(8.0+)
MySQL 8.0及以上版本支持JSON_ARRAYAGG和JSON_OBJECT函数,写法类似:
SELECT o.orderid, o.date, -- 手动指定要包含的字段,转成JSON对象再聚合为数组 JSON_ARRAYAGG( JSON_OBJECT( 'itemdescription', oi.itemdescription, 'price', oi.price, 'quantity', oi.quantity ) ) AS orderitems FROM orders o LEFT JOIN orderitems oi ON o.orderid = oi.orderid GROUP BY o.orderid, o.date;
如果想直接把整行转成JSON对象,也可以简化成JSON_ARRAYAGG(oi),不过这样会包含orderid等关联字段,你可以根据需求调整。
3. SQL Server
SQL Server用FOR JSON子句来生成嵌套JSON,比如:
SELECT o.orderid, o.date, -- 用FOR JSON AUTO生成嵌套的JSON数组 JSON_QUERY( (SELECT itemdescription, price, quantity FROM orderitems oi WHERE oi.orderid = o.orderid FOR JSON PATH) ) AS orderitems FROM orders o;
这里用JSON_QUERY是为了避免SQL Server自动给JSON字符串加转义符,确保返回的是原生JSON格式。
注意:你原来的写法为什么可能报错?
你给出的示例SQL如果直接运行,大部分数据库会报错——因为子查询返回了多行结果,而单个SELECT列默认只能接受单值。解决的核心就是用聚合函数把多行结果打包成一个JSON数组(或者数据库支持的其他集合类型),这样就能作为单个字段返回了。
如果你的需求不是转JSON,只是想返回表类型的结果,部分数据库(比如PostgreSQL)支持返回数组或自定义表值类型,但这种方式在应用层处理起来不如JSON通用,所以还是转JSON的方案更常用。
内容的提问来源于stack exchange,提问作者The Innovative Technologist

