MySQL聚合了JSON对象的总和

时间:2018-03-26 11:54:59

标签: mysql sql json

我创建了新表并将详细信息作为JSON数据类型。我试图得到所有记录的总和。我能够获得每个值,但我不知道如何使用group by选项获得总和。

CREATE TABLE `Sample` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `details` json DEFAULT NULL,
  PRIMARY KEY (`id`)
)  CHARSET=latin1;

样本数据

 1. [{"id": 1, "name": "T1", "amount": "34.34", "percentage": "45"}, {"id": 3, "name": "T3", "amount": "30.34", "percentage": "45"}, {"id": 2, "name": "T2", "amount": "14.34", "percentage": "15"}]

 2. [{"id": 1, "name": "T1", "amount": "34.34", "percentage": "45"}, {"id": 2, "name": "T2", "amount": "30.34", "percentage": "45"}, {"id": 4, "name": "T4", "amount": "14.34", "percentage": "15"}]

我想要这两个记录的聚合组

输出数据

   [{"id": 1, "name": "T1", "amount": "68.68", "percentage": "45"}, {"id": 3, "name"`enter code here`: "T3", "amount": "30.34", "percentage": "45"}, {"id": 2, "name": "T2", "amount": "44.68", "percentage": "60"}, {"id": 4, "name": "T4", "amount": "14.34", "percentage": "15"}]

我尝试使用JSON_EXTRACT(详情," $ [*]")但是没有用完

4 个答案:

答案 0 :(得分:4)

更新:好的

首先,我肯定会建议对数据进行标准化。 您是否尝试将对象存储到详细信息列中? 如果需要使用每个Sample id存储数据组,则可以使用相关表。 IE:)

样品

id int auto increment

mysql> create table Sample (id int(11) not null auto_increment, primary key(id));

详细

sample_id int 记录json

mysql> create table Details (sample_id int(11), record json);

填充数据

insert into Sample (id) values (1);
insert into Sample (id) values (2);

insert into Details (sample_id, record) values 
  (1, '{"id": 1, "name": "T1", "amount": "34.34", "percentage": "45"}'), 
  (1, '{"id": 3, "name": "T3", "amount": "30.34", "percentage": "45"}'), 
  (1, '{"id": 2, "name": "T2", "amount": "14.34", "percentage": "15"}');

insert into Details (sample_id, record) values 
  (2, '{"id": 1, "name": "T1", "amount": "34.34", "percentage": "45"}'),
  (2, '{"id": 2, "name": "T2", "amount": "30.34", "percentage": "45"}'),
  (2, '{"id": 4, "name": "T4", "amount": "14.34", "percentage": "15"}');

然后你可以做类似

的事情
SELECT (
  JSON_OBJECT('id', id, 'amount', amount, 'percentage', percentage)
) FROM (
  SELECT 
    JSON_EXTRACT(record, "$.id") as id, 
    SUM(JSON_EXTRACT(record, "$.amount")) as amount, 
    AVG(JSON_EXTRACT(record, "$.percentage")) as percentage
  FROM Details 
  GROUP BY JSON_EXTRACT(record, "$.id")
) as t 

结果

+---------------------------------------------------------------------+
| (JSON_OBJECT('id', id, 'amount', amount, 'percentage', percentage)) |
+---------------------------------------------------------------------+
| {"id": 1, "amount": 68.68, "percentage": 45}                        |
| {"id": 2, "amount": 44.68, "percentage": 30}                        |
| {"id": 3, "amount": 30.34, "percentage": 45}                        |
| {"id": 4, "amount": 14.34, "percentage": 15}                        |
+---------------------------------------------------------------------+

如果您不想(或不能)使用规范化数据集,那么您可能会考虑编写一个存储过程来循环您的详细信息列并聚合每个数据列的数据,并查询聚合两个数据集。

答案 1 :(得分:1)

由于数据似乎在每个实例中都具有相同的列,因此不清楚为什么要使用JSON。您没有描述任何无法使用传统列而不是JSON的原因。

JSON数组应存储在第二个表的多行中。

CREATE TABLE `SampleDetails` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `sample_id` INT NOT NULL,
  `name` VARCHAR(10) NOT NULL,
  `amount` DECIMAL(9,2) NOT NULL,
  `percentage` TINYINT NOT NULL,
  PRIMARY KEY (`id`)
);

INSERT INTO SampleDetails (sample_id, name, amount, percentage) VALUES
(1, 'T1', 34.34, 45},
(3, 'T3', 30.34, 45},
(2, 'T2', 14.34, 15}
(1, 'T1', 34.34, 45},
(2, 'T2', 30.34, 45},
(4, 'T4', 14.34, 15);

然后你可以使用非常简单的SQL来获得总和:

SELECT sample_id, MAX(name) AS name, 
  SUM(amount) AS amount, MAX(percentage) AS percentage
FROM SampleDetails
GROUP BY sample_id;

将该SQL查询的结果提取到您的应用程序中,然后将其格式化为JSON。每种语言都有一个用于读写JSON的包。

答案 2 :(得分:0)

如何创建自己的mysql函数?

create function x_json_sum (json_object varchar(5000), json_path varchar(5000))
returns int deterministic
begin
  declare output int default 0;
  declare i int default 0;
  while json_extract(json_object, concat(json_path, '[', i,']')) is not null do
    set output = output + json_extract(json_object, concat(json_path, '[', i,']'));
    set i = i + 1;
  end while;
  return output;
end;

结果

MariaDB [****]> select x_json_sum('{"money": [3, 4, 3]}', '$.money');
+-----------------------------------------------+
| x_json_sum('{"money": [3, 4, 3]}', '$.money') |
+-----------------------------------------------+
|                                            10 |
+-----------------------------------------------+
1 row in set (0.00 sec)

我刚刚编写了此函数,并且可以与我的示例一起使用。您可能需要做更多的验证,例如何时返回null?数据会被截断吗?功能安全性和定义者?等

您还可以组合此求和函数并创建其他函数,例如x_json_avg等。

答案 3 :(得分:-1)

你可以在这里使用ETL将jason提取到sql,然后将SQL查询应用于Aggregate