如何从单个 MySQL table 中获取按 PHP 中的多列分组的多维数组?
How to get multidimensional array grouped by multiple columns in PHP from single MySQL table?
我有 table 看起来像这样的“guids”:
id |survey_type |guid |guid_type |table_id |created_at |
2 |TYPE 1 |6C7251E3-2151-4754-A413-51899FAAF6C2 |question |2 |2022-03-20 16:14:09 |
3 |TYPE 1 |EF5AFA93-C74D-4920-A13A-17A9B43239CD |question |3 |2022-03-20 16:14:09 |
4 |TYPE 1 |5C059148-94BE-4225-B5C2-551A81B65F16 |question |4 |2022-03-20 16:14:09 |
5 |TYPE 1 |356B8A5C-1072-47A5-A508-D9BDCBA92CCC |answer |5 |2022-03-20 16:14:09 |
6 |TYPE 1 |E0CE4C26-7ABD-4162-9C8C-B4DD540AE268 |answer |6 |2022-03-20 16:14:09 |
7 |TYPE 1 |BFBC50FC-892D-43E9-A235-D76E0D0BEF29 |answer |7 |2022-03-20 16:14:09 |
8 |TYPE 2 |B9DCC5C1-CBFB-4589-98EF-4524F3958968 |survey |8 |2022-03-20 16:14:09 |
9 |TYPE 2 |C98FBFF9-6FE3-414E-BB14-08EDC8281E66 |survey |9 |2022-03-20 16:14:09 |
10 |TYPE 2 |8A780B6E-EAE0-47D6-9D05-F52B795AE617 |question |10 |2022-03-20 16:14:09 |
11 |TYPE 2 |E3818D30-BB69-4F03-B56D-B31691F8007E |question |11 |2022-03-20 16:14:09 |
12 |TYPE 2 |24C81BEF-BFCE-4964-AB01-F3579251313D |answer |12 |2022-03-20 16:14:09 |
13 |TYPE 3 |59381701-AFBC-48F8-AECE-DB3702EE2B15 |answer |13 |2022-03-20 16:14:09 |
14 |TYPE 3 |7F4AC694-74DC-4BEA-ACFB-D8F070769FEE |answer |14 |2022-03-20 16:14:09 |
15 |TYPE 3 |B5C405B9-BA7E-471A-87DD-B69D9757276F |survey |15 |2022-03-20 16:14:09 |
我想以此格式获取数据:
Array
(
[survey_type] => Array
(
[guid_type] => Array
(
[table_id] => guid
...
)
... // all guid types
)
... // all survey types
)
基本上,我需要使用多列来构建包含分组数据的嵌套数组。
我知道我可以像这样使用 foreach 循环实现该结构:
// select existing guids
$this->db->select('*')
->from('guids');
$query = $this->db->get();
$existing_guids = $query->result_array();
$formated_guids = [];
foreach($existing_guids as $key => $guid_data) {
$formated_guids[$guid_data['survey_type']][$guid_data['guid_type']][$guid_data['table_id']] = $guid_data['guid'];
}
但如果可能的话,我希望在数据库层有一个更优化的解决方案,因为这个 table 预计会有数百万行并且遍历整个 table 似乎不是最优化的方式。
我尝试了 GROUP_CONCAT mysql 命令,但未能生成所需的结构
SELECT `survey_type`, GROUP_CONCAT(`guid_type`) AS `guid_types` FROM guids GROUP BY `survey_type`
模拟数据的预期结果:
Array
(
[TYPE 1] => Array // survey type column
(
[question] => Array // guid_type column
(
// table_id => guid
[1] => C8D21BD8-DA62-43C6-8E0D-0524D4F093B6
[2] => 6C7251E3-2151-4754-A413-51899FAAF6C2
...
)
[survey] => Array
(
[14] => B8B1F361-34A2-430E-9C0E-EB0C515B4E79
...
)
[answer] => Array
(
[2906] => 1A2F133E-0491-4117-AE2E-E3A823B66FBD...
)
),
[TYPE 2] => Array
(
... // same structure as above
)
首先,我建议您坚持使用您的代码解决方案。 运行 一个简单的 SQL 查询,并处理结果,将它们整理成您想要的嵌套数组结构。你已经有了那个代码,如果你需要改变它,它更容易调试,也更容易改变。
我已经像您描述的那样实现了在 SQL 查询中创建嵌套结构的方法。这非常困难,而且 SQL 查询非常复杂,如果我们需要修改嵌套结构的内容,这将是将来的维护问题。
我在SQL查询中使用的解决方案是使用多级派生table子查询,并在每个级别使用JSON函数生成聚合JSON结果.这需要使用 MySQL 5.7 或更高版本,因为这些 JSON 功能在 MySQL.
的早期版本中未实现
演示测试数据:
create table if not exists mytable ( id int primary key, survey_type varchar(20), guid char(36), guid_type varchar(20), table_id int, created_at datetime );
insert into mytable values
(2 ,'TYPE 1','6C7251E3-2151-4754-A413-51899FAAF6C2','question','2','2022-03-20 16:14:09'),
(3 ,'TYPE 1','EF5AFA93-C74D-4920-A13A-17A9B43239CD','question','3','2022-03-20 16:14:09'),
(4 ,'TYPE 1','5C059148-94BE-4225-B5C2-551A81B65F16','question','4','2022-03-20 16:14:09'),
(5 ,'TYPE 1','356B8A5C-1072-47A5-A508-D9BDCBA92CCC','answer','5','2022-03-20 16:14:09'),
(6 ,'TYPE 1','E0CE4C26-7ABD-4162-9C8C-B4DD540AE268','answer','6','2022-03-20 16:14:09'),
(7 ,'TYPE 1','BFBC50FC-892D-43E9-A235-D76E0D0BEF29','answer','7','2022-03-20 16:14:09'),
(8 ,'TYPE 2','B9DCC5C1-CBFB-4589-98EF-4524F3958968','survey','8','2022-03-20 16:14:09'),
(9 ,'TYPE 2','C98FBFF9-6FE3-414E-BB14-08EDC8281E66','survey','9','2022-03-20 16:14:09'),
(10 ,'TYPE 2','8A780B6E-EAE0-47D6-9D05-F52B795AE617','question','10','2022-03-20 16:14:09'),
(11 ,'TYPE 2','E3818D30-BB69-4F03-B56D-B31691F8007E','question','11','2022-03-20 16:14:09'),
(12 ,'TYPE 2','24C81BEF-BFCE-4964-AB01-F3579251313D','answer','12','2022-03-20 16:14:09'),
(13 ,'TYPE 3','59381701-AFBC-48F8-AECE-DB3702EE2B15','answer','13','2022-03-20 16:14:09'),
(14 ,'TYPE 3','7F4AC694-74DC-4BEA-ACFB-D8F070769FEE','answer','14','2022-03-20 16:14:09'),
(15 ,'TYPE 3','B5C405B9-BA7E-471A-87DD-B69D9757276F','survey','15','2022-03-20 16:14:09');
示例查询:
select json_pretty(json_objectagg(survey_type, g)) as j
from (
select survey_type, json_objectagg(guid_type, t) as g
from (
select survey_type, guid_type, json_objectagg(table_id, guid) as t
from mytable
group by survey_type, guid_type
) as t
group by survey_type
) as g;
输出:
{
"TYPE 1": {
"answer": {
"5": "356B8A5C-1072-47A5-A508-D9BDCBA92CCC",
"6": "E0CE4C26-7ABD-4162-9C8C-B4DD540AE268",
"7": "BFBC50FC-892D-43E9-A235-D76E0D0BEF29"
},
"question": {
"2": "6C7251E3-2151-4754-A413-51899FAAF6C2",
"3": "EF5AFA93-C74D-4920-A13A-17A9B43239CD",
"4": "5C059148-94BE-4225-B5C2-551A81B65F16"
}
},
"TYPE 2": {
"answer": {
"12": "24C81BEF-BFCE-4964-AB01-F3579251313D"
},
"survey": {
"8": "B9DCC5C1-CBFB-4589-98EF-4524F3958968",
"9": "C98FBFF9-6FE3-414E-BB14-08EDC8281E66"
},
"question": {
"10": "8A780B6E-EAE0-47D6-9D05-F52B795AE617",
"11": "E3818D30-BB69-4F03-B56D-B31691F8007E"
}
},
"TYPE 3": {
"answer": {
"13": "59381701-AFBC-48F8-AECE-DB3702EE2B15",
"14": "7F4AC694-74DC-4BEA-ACFB-D8F070769FEE"
},
"survey": {
"15": "B5C405B9-BA7E-471A-87DD-B69D9757276F"
}
}
}
将该结果提取到您的客户端应用程序中。这是一个长字符串,所以我希望您的数据不超过 MySQL 的 max_allowed_packet
长度。
使用 json_decode() 将字符串转换为所需的嵌套数组。
我有 table 看起来像这样的“guids”:
id |survey_type |guid |guid_type |table_id |created_at |
2 |TYPE 1 |6C7251E3-2151-4754-A413-51899FAAF6C2 |question |2 |2022-03-20 16:14:09 |
3 |TYPE 1 |EF5AFA93-C74D-4920-A13A-17A9B43239CD |question |3 |2022-03-20 16:14:09 |
4 |TYPE 1 |5C059148-94BE-4225-B5C2-551A81B65F16 |question |4 |2022-03-20 16:14:09 |
5 |TYPE 1 |356B8A5C-1072-47A5-A508-D9BDCBA92CCC |answer |5 |2022-03-20 16:14:09 |
6 |TYPE 1 |E0CE4C26-7ABD-4162-9C8C-B4DD540AE268 |answer |6 |2022-03-20 16:14:09 |
7 |TYPE 1 |BFBC50FC-892D-43E9-A235-D76E0D0BEF29 |answer |7 |2022-03-20 16:14:09 |
8 |TYPE 2 |B9DCC5C1-CBFB-4589-98EF-4524F3958968 |survey |8 |2022-03-20 16:14:09 |
9 |TYPE 2 |C98FBFF9-6FE3-414E-BB14-08EDC8281E66 |survey |9 |2022-03-20 16:14:09 |
10 |TYPE 2 |8A780B6E-EAE0-47D6-9D05-F52B795AE617 |question |10 |2022-03-20 16:14:09 |
11 |TYPE 2 |E3818D30-BB69-4F03-B56D-B31691F8007E |question |11 |2022-03-20 16:14:09 |
12 |TYPE 2 |24C81BEF-BFCE-4964-AB01-F3579251313D |answer |12 |2022-03-20 16:14:09 |
13 |TYPE 3 |59381701-AFBC-48F8-AECE-DB3702EE2B15 |answer |13 |2022-03-20 16:14:09 |
14 |TYPE 3 |7F4AC694-74DC-4BEA-ACFB-D8F070769FEE |answer |14 |2022-03-20 16:14:09 |
15 |TYPE 3 |B5C405B9-BA7E-471A-87DD-B69D9757276F |survey |15 |2022-03-20 16:14:09 |
我想以此格式获取数据:
Array
(
[survey_type] => Array
(
[guid_type] => Array
(
[table_id] => guid
...
)
... // all guid types
)
... // all survey types
)
基本上,我需要使用多列来构建包含分组数据的嵌套数组。 我知道我可以像这样使用 foreach 循环实现该结构:
// select existing guids
$this->db->select('*')
->from('guids');
$query = $this->db->get();
$existing_guids = $query->result_array();
$formated_guids = [];
foreach($existing_guids as $key => $guid_data) {
$formated_guids[$guid_data['survey_type']][$guid_data['guid_type']][$guid_data['table_id']] = $guid_data['guid'];
}
但如果可能的话,我希望在数据库层有一个更优化的解决方案,因为这个 table 预计会有数百万行并且遍历整个 table 似乎不是最优化的方式。
我尝试了 GROUP_CONCAT mysql 命令,但未能生成所需的结构
SELECT `survey_type`, GROUP_CONCAT(`guid_type`) AS `guid_types` FROM guids GROUP BY `survey_type`
模拟数据的预期结果:
Array
(
[TYPE 1] => Array // survey type column
(
[question] => Array // guid_type column
(
// table_id => guid
[1] => C8D21BD8-DA62-43C6-8E0D-0524D4F093B6
[2] => 6C7251E3-2151-4754-A413-51899FAAF6C2
...
)
[survey] => Array
(
[14] => B8B1F361-34A2-430E-9C0E-EB0C515B4E79
...
)
[answer] => Array
(
[2906] => 1A2F133E-0491-4117-AE2E-E3A823B66FBD...
)
),
[TYPE 2] => Array
(
... // same structure as above
)
首先,我建议您坚持使用您的代码解决方案。 运行 一个简单的 SQL 查询,并处理结果,将它们整理成您想要的嵌套数组结构。你已经有了那个代码,如果你需要改变它,它更容易调试,也更容易改变。
我已经像您描述的那样实现了在 SQL 查询中创建嵌套结构的方法。这非常困难,而且 SQL 查询非常复杂,如果我们需要修改嵌套结构的内容,这将是将来的维护问题。
我在SQL查询中使用的解决方案是使用多级派生table子查询,并在每个级别使用JSON函数生成聚合JSON结果.这需要使用 MySQL 5.7 或更高版本,因为这些 JSON 功能在 MySQL.
的早期版本中未实现演示测试数据:
create table if not exists mytable ( id int primary key, survey_type varchar(20), guid char(36), guid_type varchar(20), table_id int, created_at datetime );
insert into mytable values
(2 ,'TYPE 1','6C7251E3-2151-4754-A413-51899FAAF6C2','question','2','2022-03-20 16:14:09'),
(3 ,'TYPE 1','EF5AFA93-C74D-4920-A13A-17A9B43239CD','question','3','2022-03-20 16:14:09'),
(4 ,'TYPE 1','5C059148-94BE-4225-B5C2-551A81B65F16','question','4','2022-03-20 16:14:09'),
(5 ,'TYPE 1','356B8A5C-1072-47A5-A508-D9BDCBA92CCC','answer','5','2022-03-20 16:14:09'),
(6 ,'TYPE 1','E0CE4C26-7ABD-4162-9C8C-B4DD540AE268','answer','6','2022-03-20 16:14:09'),
(7 ,'TYPE 1','BFBC50FC-892D-43E9-A235-D76E0D0BEF29','answer','7','2022-03-20 16:14:09'),
(8 ,'TYPE 2','B9DCC5C1-CBFB-4589-98EF-4524F3958968','survey','8','2022-03-20 16:14:09'),
(9 ,'TYPE 2','C98FBFF9-6FE3-414E-BB14-08EDC8281E66','survey','9','2022-03-20 16:14:09'),
(10 ,'TYPE 2','8A780B6E-EAE0-47D6-9D05-F52B795AE617','question','10','2022-03-20 16:14:09'),
(11 ,'TYPE 2','E3818D30-BB69-4F03-B56D-B31691F8007E','question','11','2022-03-20 16:14:09'),
(12 ,'TYPE 2','24C81BEF-BFCE-4964-AB01-F3579251313D','answer','12','2022-03-20 16:14:09'),
(13 ,'TYPE 3','59381701-AFBC-48F8-AECE-DB3702EE2B15','answer','13','2022-03-20 16:14:09'),
(14 ,'TYPE 3','7F4AC694-74DC-4BEA-ACFB-D8F070769FEE','answer','14','2022-03-20 16:14:09'),
(15 ,'TYPE 3','B5C405B9-BA7E-471A-87DD-B69D9757276F','survey','15','2022-03-20 16:14:09');
示例查询:
select json_pretty(json_objectagg(survey_type, g)) as j
from (
select survey_type, json_objectagg(guid_type, t) as g
from (
select survey_type, guid_type, json_objectagg(table_id, guid) as t
from mytable
group by survey_type, guid_type
) as t
group by survey_type
) as g;
输出:
{
"TYPE 1": {
"answer": {
"5": "356B8A5C-1072-47A5-A508-D9BDCBA92CCC",
"6": "E0CE4C26-7ABD-4162-9C8C-B4DD540AE268",
"7": "BFBC50FC-892D-43E9-A235-D76E0D0BEF29"
},
"question": {
"2": "6C7251E3-2151-4754-A413-51899FAAF6C2",
"3": "EF5AFA93-C74D-4920-A13A-17A9B43239CD",
"4": "5C059148-94BE-4225-B5C2-551A81B65F16"
}
},
"TYPE 2": {
"answer": {
"12": "24C81BEF-BFCE-4964-AB01-F3579251313D"
},
"survey": {
"8": "B9DCC5C1-CBFB-4589-98EF-4524F3958968",
"9": "C98FBFF9-6FE3-414E-BB14-08EDC8281E66"
},
"question": {
"10": "8A780B6E-EAE0-47D6-9D05-F52B795AE617",
"11": "E3818D30-BB69-4F03-B56D-B31691F8007E"
}
},
"TYPE 3": {
"answer": {
"13": "59381701-AFBC-48F8-AECE-DB3702EE2B15",
"14": "7F4AC694-74DC-4BEA-ACFB-D8F070769FEE"
},
"survey": {
"15": "B5C405B9-BA7E-471A-87DD-B69D9757276F"
}
}
}
将该结果提取到您的客户端应用程序中。这是一个长字符串,所以我希望您的数据不超过 MySQL 的 max_allowed_packet
长度。
使用 json_decode() 将字符串转换为所需的嵌套数组。