
本教程旨在解决从mysql多表(如产品与图片)中高效获取具有一对多关系的数据,并将其聚合为前端所需的嵌套json结构。文章将对比传统n+1查询的低效性,探讨sql层(join、json函数)和应用层(php)数据聚合的策略与实现,旨在提供优化查询性能和数据处理的专业指导,帮助开发者构建高效的数据服务。
在现代Web应用开发中,从关系型数据库中获取具有一对多关系的数据(例如,一个产品对应多张图片)并将其以嵌套的JSON格式返回给前端是一个常见的需求。传统的做法,如对每个产品单独查询其图片(即N+1查询问题),会导致大量的数据库往返,严重影响应用性能。本教程将深入探讨如何通过优化SQL查询和应用层数据处理,高效地实现这一目标。
我们以一个典型的产品及其图片为例,涉及两张表:products(产品信息)和 product_images(产品图片)。
products 表:
| id | product_name | price |
|---|---|---|
| 1 | product name 1 | 15 |
| 2 | product name 2 | 23.25 |
| 3 | product name 3 | 50 |
product_images 表:
| id | product_id | image |
|---|---|---|
| 1 | 1 | e5j7eof75y6ey6ke97et5g9thec7e5fnhv54eg9t6gh65bf.png |
| 2 | 1 | sefuywe75wjmce5y98nvb7v939ty89e5h45mg5879dghkjh.png |
| 3 | 1 | 7u5f9e6jumw75f69w6jc89fwmykdy0tw78if6575m7489tf.png |
我们的目标是生成以下类似的嵌套JSON结构:
{
"id": 1,
"product_name": "product name 1",
"price": 15,
"images": [
{
"id": 1,
"image": "e5j7eof75y6ey6ke97et5g9thec7e5fnhv54eg9t6gh65bf.png"
},
{
"id": 2,
"image": "sefuywe75wjmce5y98nvb7v939ty89e5h45mg5879dghkjh.png"
}
]
}许多开发者初次面对此类需求时,可能会采用以下PHP代码逻辑:
// 伪代码示例
$products = $db->query("SELECT id, product_name, price FROM products")->fetchAll();
foreach ($products as &$product) {
$product_id = $product['id'];
$images = $db->query("SELECT id, image FROM product_images WHERE product_id = {$product_id}")->fetchAll();
$product['images'] = $images;
}
echo json_encode($products);这种方法的问题在于,如果有N个产品,它将执行1次产品查询和N次图片查询,总共N+1次数据库查询。当N值较大时,这将导致巨大的性能开销。
对于MySQL 5.7及更高版本,引入的JSON函数提供了在数据库层面直接构建JSON结构的能力,可以实现单次查询返回接近目标JSON结构的数据。
SELECT
p.id,
p.product_name,
p.price,
JSON_ARRAYAGG(
JSON_OBJECT('id', pi.id, 'image', pi.image)
) AS images
FROM
products p
LEFT JOIN
product_images pi ON p.id = pi.product_id
GROUP BY
p.id, p.product_name, p.price;代码解释:
注意事项:
会译·对照式翻译
会译是一款AI智能翻译浏览器插件,支持多语种对照式翻译
79
查看详情
替代方案(旧版本MySQL):GROUP_CONCAT
对于不支持JSON函数的旧版本MySQL,可以使用 GROUP_CONCAT 来将图片信息连接成字符串,然后在应用层解析。
SELECT
p.id,
p.product_name,
p.price,
GROUP_CONCAT(CONCAT_WS(':', pi.id, pi.image) SEPARATOR ';') AS images_str
FROM
products p
LEFT JOIN
product_images pi ON p.id = pi.product_id
GROUP BY
p.id, p.product_name, p.price;此方法需要PHP在接收到 images_str 后,手动分割字符串并构建图片数组,增加了应用层的处理复杂性。
这种方法通常被认为是性能和灵活性之间较好的平衡点,尤其适用于处理大量数据。它通过两次高效的数据库查询,将数据拉取到应用层,再在应用层进行聚合。
步骤:
<?php
// 模拟从数据库获取的产品数据
$products_flat = [
['id' => 1, 'product_name' => 'product name 1', 'price' => 15],
['id' => 2, 'product_name' => 'product name 2', 'price' => 23.25],
['id' => 3, 'product_name' => 'product name 3', 'price' => 50],
];
// 从产品数据中提取所有产品ID,用于查询图片
$product_ids = array_column($products_flat, 'id');
$product_ids_str = implode(',', $product_ids); // 示例:'1,2,3'
// 模拟从数据库获取的图片数据
// 实际查询可能类似:SELECT id, product_id, image FROM product_images WHERE product_id IN ({$product_ids_str});
$images_flat = [
['id' => 1, 'product_id' => 1, 'image' => 'e5j7eof75y6ey6ke97et5g9thec7e5fnhv54eg9t6gh65bf.png'],
['id' => 2, 'product_id' => 1, 'image' => 'sefuywe75wjmce5y98nvb7v939ty89e5h45mg5879dghkjh.png'],
['id' => 3, 'product_id' => 1, 'image' => '7u5f9e6jumw75f69w6jc89fwmykdy0tw78if6575m7489tf.png'],
// 假设产品2和产品3没有图片,或者图片数据中没有它们
];
// 第一步:将产品列表转换为以ID为键的关联数组,并初始化图片数组
$products_indexed = [];
foreach ($products_flat as $product) {
$product['images'] = []; // 初始化为空数组
$products_indexed[$product['id']] = $product;
}
// 第二步:遍历图片列表,将其添加到对应的产品中
foreach ($images_flat as $image) {
$product_id = $image['product_id'];
if (isset($products_indexed[$product_id])) {
// 移除图片数据中的 product_id,因为在嵌套结构中不再需要
unset($image['product_id']);
$products_indexed[$product_id]['images'][] = $image;
}
}
// 如果需要将关联数组转换回索引数组(例如,为了前端接收的JSON数组格式)
$final_products = array_values($products_indexed);
// 输出结果(通常会进行 json_encode)
echo '<pre class="brush:php;toolbar:false;">';
var_export($final_products);
echo '';
/*
期望输出结构示例:
array (
0 =>
array (
'id' => 1,
'product_name' => 'product name 1',
'price' => 15,
'images' =>
array (
0 =>
array (
'id' => 1,
'image' => 'e5j7eof75y6ey6ke97et5g9thec7e5fnhv54eg9t6gh65bf.png',
),
1 =>
array (
'id' => 2,
'image' => 'sefuywe75wjmce5y98nvb7v939ty89e5h45mg5879dghkjh.png',
),
2 =>
array (
'id' => 3,
'image' => '7u5f9e6jumw75f69w6jc89fwmykdy0tw78if6575m7489tf.png',
),
),
),
1 =>
array (
'id' => 2,
'product_name' => 'product name 2',
'price' => 23.25,
'images' =>
array (
),
),
2 =>
array (
'id' => 3,
'product_name' => 'product name 3',
'price' => 50,
'images' =>
array (
),
),
)
*/代码解释:
性能优势:
在构建产品及其图片等一对多关系的嵌套数据结构时,选择合适的策略至关重要:
通过理解和应用这些优化策略,开发者可以显著提升数据查询和处理的效率,为用户提供更流畅的应用体验。
以上就是MySQL多表关联查询与应用层数据聚合:构建产品及其图片嵌套结构的详细内容,更多请关注php中文网其它相关文章!
# php
# js
# 前端
# mysql
# 中山公司推广网站价格
# 淘宝推广技巧网站
# 线上营销推广是什么意思
# 晋江网站建设制作报价
# 情人节推广营销话术
# 榆社网站推广策略
# 宜州关键词排名优化
# 上海知名seo推广机构
# 鞍山双语网站建设
# 临沂专业网站优化服务
# 数据库查询
# 两次
# 推荐使用
# 转换为
# 数据结构
# 遍历
# 已有
# 管理系统
# 应用层
# json数组
# 应用开发
# 编程语言
# 字节
# 大数据
# json
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
Go反射进阶:访问内嵌结构体中的被遮蔽方法
从HTML表单获取逗号分隔值并转换为NumPy数组进行预测
响应式设计中动态背景颜色条的实现指南
三星M34录音变声问题_Samsung M34麦克风调整
Python中对象引用与链表属性赋值的机制解析
汽水音乐在线听歌网页版 汽水音乐在线听歌网页版入口
解决Pandas DataFrame高度碎片化警告:高效创建多列的策略
C++ bind函数使用教程_C++参数绑定与函数适配器的应用
蜻蜓FM如何设置移动流量播放
包子漫画官网链接官方地址 包子漫画在线观看官网首页入口
铁路12306入口 铁路12306官网版入口登录网址
空腹吃苹果好吗 苹果空腹摄入指南
如何使用 Optional 类型并满足 Pylint 的类型检查
《三角洲行动》战斗步枪与机枪类改装代码分享
抖音号升级企业号怎么改名字?升级企业号有哪些好处?
《随手记》关闭首页消息推送方法
使用逻辑应用(Logic Apps)自动处理邮件附件中的XML到Excel
基于 Flink 和 Kafka 实现高效流处理:连续查询与时间窗口
windows10怎么开启卓越性能_windows10电源选项代码激活
电脑从睡眠中被自动唤醒怎么办_Windows唤醒源事件查看与禁用【解决】
快手缓存清理方法
win11怎么设置默认终端为Windows Terminal Win11替代CMD和PowerShell【技巧】
J*aScript 数值去小数位处理:多种方法与实践
《i莞家》修改昵称方法
Sublime Text怎么关闭自动完成_Sublime禁用Auto Complete设置
如何在Python中安全地将环境变量转换为整数并满足Mypy类型检查
J*aScript与CSS动画:实现平滑顺序淡入淡出效果并解决显示冲突
电脑双系统如何安装和卸载 Windows和Linux双系统安装教程【详解】
向往的生活小游戏启动处_向往的生活小游戏立即启动
《搜书吧》阅读书籍方法
百度识图图像分析 百度识图识别平台
荣耀magicv5怎么上手测评
《深林》冬季章节图文攻略
电脑没有声音了怎么办 电脑声音问题的全面排查与修复指南【详解】
抖音商城官网是什么_抖音商城官方网址与访问方法
苹果手机手电筒无法开启
如何在mysql中比较InnoDB和MyISAM区别
《via浏览器》强制缩放网页设置方法
Python实战:高效处理实时数据流中的最小/最大值
《植物大战僵尸3》火龙草作用介绍
《猎聘》筛选猎头岗位方法
Google Drive API 认证:服务账户与OAuth 2.0的选择与实践
广州地铁app准妈咪徽章领取方法
search中maxlength属性用法解析
快手极速版在线体验区 快手极速版网页体验入口
5G和6G的连接密度有什么区别 6G每平方公里能连接多少设备
PHP使用DOMDocument与XPath精准追加XML元素教程
疯狂小鸟微信小游戏入口 疯狂小鸟网页版秒玩
实时数据流中高效查找最小值与最大值
使用document.execCommand实现Web文本编辑器加粗/取消加粗
2025-11-21
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。