简介
JSON_ARRAYAGG是一个SQL聚合函数,用于将一组SQL表达式的结果转换为一个JSON数组。这个函数非常有用,特别是在需要将数据库查询结果以JSON格式返回时。
应用场景:
聚合函数主要用于查询带有树形结构的数据,比如省市区查询,一条语句即可完成省市区json结构。
比如我们要想一次性查询出如下数据结构,就可以使用聚合函数:
[{
"id": 0, "text": "北京市", "value": 110100, "children": [{
"id": 110111, "text": "房山区", "value": 110111}, {
"id": 110109, "text": "门头沟区", "value": 110109}, {
"id": 110113, "text": "顺义区", "value": 110113}, {
"id": 110105, "text": "朝阳区", "value": 110105}, {
"id": 110112, "text": "通州区", "value": 110112}, {
"id": 110102, "text": "西城区", "value": 110102}, {
"id": 110101, "text": "东城区", "value": 110101}, {
"id": 110107, "text": "石景山区", "value": 110107}, {
"id": 110108, "text": "海淀区", "value": 110108}, {
"id": 110114, "text": "昌平区", "value": 110114}, {
"id": 110119, "text": "延庆区", "value": 110119}, {
"id": 110116, "text": "怀柔区", "value": 110116}, {
"id": 110118, "text": "密云区", "value": 110118}, {
"id": 110117, "text": "平谷区", "value": 110117}, {
"id": 110115, "text": "大兴区", "value": 110115}, {
"id": 110106, "text": "丰台区", "value": 110106}]}]
如何使用:
语法及使用
JSON_ARRAYAGG(expression)
expression:可以是任何评估为JSON对象、JSON数组、数字文字、文本文字或NULL的SQL表达式。
expression为单类型数组时间
CREATE TABLE id_table (id int(10));
INSERT INTO id_table VALUES (624);
INSERT INTO id_table VALUES (925);
INSERT INTO id_table VALUES (585);
SELECT JSON_ARRAYAGG(id ORDER BY id) AS id_numbers FROM id_table;
id_numbers
--------------
[585, 624, 925]
expression为json对象
CREATE TABLE `hqmall_region` (
`id` int NOT NULL AUTO_INCREMENT,
`pid` int NOT NULL DEFAULT '0' COMMENT '行政区域父ID',
`name` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '行政区域名称',
`type` tinyint NOT NULL DEFAULT '0' COMMENT '行政区域类型,如如1则是省, 如果是2则是市,如果是3则是区县',
`code` int NOT NULL DEFAULT '0' COMMENT '行政区域编码',
PRIMARY KEY (`id`) USING BTREE,
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC COMMENT='行政区域表';
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (1, '北京市', 110000);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (36, '北京市', 110100);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (427, '房山区', 110111);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (428, '门头沟区', 110109);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (429, '顺义区', 110113);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (430, '朝阳区', 110105);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (431, '通州区', 110112);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (432, '西城区', 110102);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (433, '东城区', 110101);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (434, '石景山区', 110107);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (435, '海淀区', 110108);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (436, '昌平区', 110114);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (437, '延庆区', 110119);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (438, '怀柔区', 110116);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (439, '密云区', 110118);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (440, '平谷区', 110117);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (441, '大兴区', 110115);
INSERT INTO `hqmall`.`hqmall_region`(`id`, `name`, `code`) VALUES (442, '丰台区', 110106);
SELECT JSON_ARRAYAGG(JSON_OBJECT( 'id',0,'text', r2.NAME,'value', r2.CODE,'children', (SELECT JSON_ARRAYAGG( JSON_OBJECT( 'id', r3.CODE, 'text', r3.NAME, 'value', r3.CODE ) ) FROM hqmall_region r3 WHERE r3.pid = r2.id ))) FROM hqmall_region r1 JOIN hqmall_region r2 ON r1.id = r2.pid WHERE r1.pid = 0 AND r1.CODE LIKE '11%';
-- 结果
[{
"id": 0, "text": "北京市", "value": 110100, "children": [{
"id": 110111, "text": "房山区", "value": 110111}, {
"id": 110109, "text": "门头沟区", "value": 110109}, {
"id": 110113, "text": "顺义区", "value": 110113}, {
"id": 110105, "text": "朝阳区", "value": 110105}, {
"id": 110112, "text": "通州区", "value": 110112}, {
"id": 110102, "text": "西城区", "value": 110102}, {
"id": 110101, "text": "东城区", "value": 110101}, {
"id": 110107, "text": "石景山区", "value": 110107}, {
"id": 110108, "text": "海淀区", "value": 110108}, {
"id": 110114, "text": "昌平区", "value": 110114}, {
"id": 110119, "text": "延庆区", "value": 110119}, {
"id": 110116, "text": "怀柔区", "value": 110116}, {
"id": 110118, "text": "密云区", "value": 110118}, {
"id": 110117, "text": "平谷区", "value": 110117}, {
"id": 110115, "text": "大兴区", "value": 110115}, {
"id": 110106, "text": "丰台区", "value": 110106}]}]
为什么会出现乱码
在mysql客户端工具中查询,显示正常,但是这个函数放在代码中,查询出来却成了乱码,这是因为mysql聚合函数放回的数据并非字符串,代码中持久层框架解析出问题,就会出现乱码。
解决乱码问题
这时我们需要对聚合函数返回的数据做转换,转为字符串,使用cast函数。具体操作:
SELECT cast(JSON_ARRAYAGG(JSON_OBJECT( 'id',0,'text', r2.NAME,'value', r2.CODE,'children', (SELECT JSON_ARRAYAGG( JSON_OBJECT( 'id', r3.CODE, 'text', r3.NAME, 'value', r3.CODE ) ) FROM hqmall_region r3 WHERE r3.pid = r2.id ))) AS char) FROM hqmall_region r1 JOIN hqmall_region r2 ON r1.id = r2.pid WHERE r1.pid = 0 AND r1.CODE LIKE '11%';
总结:
此函数尽量使用在一些数据比较少的嵌套数据结构查询中,不用再代码中做二次嵌套,提升开发效率。