我有以下Mysql数据库结构
[Table - Category1]
[Table Category1 -> Category2 ] (One to N relation)
[Table - Category2]
[Table Category2 -> Item ] (One to N relation)
[Table - Item]
我希望在PHP中使用以下结构将所有内容都放入数组中
$arr[$i]['name'] = 'name of something in category1';
$arr[$i]['data'][$j]['name'] = 'name of something in category2';
$arr[$i]['data'][$j]['data'][$k]['name'] = 'name of something in item';
所以基本上我不知道我是否应该使用一个" heavy"使用JOIN的sql请求,如下所示,或使用迭代方法
加入请求
SELECT c1.name as c1name, c2.name as c2name, i.name
FROM category1 c1
LEFT JOIN category1_to_category2 c1tc2 ON c1.id = c1tc2.id_category1
LEFT JOIN category2 c2 ON c1tc2.id_category2 = c2.id
LEFT JOIN category2_to_item c2ti ON c2.id = c2ti.id_category2
LEFT JOIN item i ON c2ti.id_item = i.id
迭代方法
$sql = 'SELECT id, name FROM category1';
$result = $mysqli->query($sql);
$arr = array();
$i = 0;
while ($arr[$i] = $result->fetch_assoc()) {
$join = $mysqli->query('SELECT c2.id, c2.name FROM category2 c2 LEFT JOIN category1_to_category2 c1tc2 ON c2.id = c1tc2.id_category 2 WHERE c1tc2.id_category1 = '.$arr[$i]['id']);
$j = 0;
while ($arr[$i]['data'][$j] = $join->fetch_assoc())
/* same request as above but with items */
$i++;
}
迭代解决方案将产生大约10 * 20的请求,这对我来说似乎很重要,这就是为什么我会选择第一个解决方案(4 JOIN单个请求)。 但是,使用单个请求解决方案,我的数组将看起来像
$arr[0]['c1name'];
$arr[0]['c2name'];
$arr[0]['iname'];
并且需要一些PHP traitement来获取我需要在HTML页面的选项卡中显示的所需数组。所以我的问题是,有一个大的SQL请求与一些PHP数组操作或没有PHP数组操作有多个小请求更好吗?我知道在大多数情况下,从SQL获取所有数据是一个更好的解决方案,但在这种情况下,我不确定。顺便说一句,我唯一的考虑是我的网页加载时间。
提前感谢您的帮助=)。
答案 0 :(得分:1)
通常更好,并且您的示例也不例外,让SQL服务器尽可能多地执行数据格式化和迭代,因为SQL服务器通常比常用编程语言更有效地完成任务。
除此之外,您正在减少服务器的查询负载,并且您有充分的理由使用复杂的连接。
唯一的缺点是复杂的SQL查询很难格式化和调试,如果还没有使用第三方SQL工具,我建议你来一个。
答案 1 :(得分:0)
要使用Wobbles(我同意)的答案,我建议您执行单个查询,但是存储c1name,c2name和iname中每个的最后一个键。当这些更改时,您可以递增相关的数组下标并再次初始化较低级别的数组,以构建数组。
这样的事情: -
<?php
$sql = "SELECT c1.name AS c1name, c2.name AS c2name, i.name AS iname
FROM category1 c1
LEFT JOIN category1_to_category2 c1tc2 ON c1.id = c1tc2.id_category1
LEFT JOIN category2 c2 ON c1tc2.id_category2 = c2.id
LEFT JOIN category2_to_item c2ti ON c2.id = c2ti.id_category2
LEFT JOIN item i ON c2ti.id_item = i.id"
$result = $mysqli->query($sql);
$arr = array();
$i = 0;
$j = 0;
$k = 0;
$c1name = '';
$c2name = '';
$iname = '';
while ($row = $result->fetch_assoc())
{
switch(true)
{
case $row['c1name'] != $c1name :
$i++;
$j = 0;
$k = 0;
$arr[$i]['name'] = $row['c1name'];
$arr[$i]['data'][$j]['name'] = $row['c2name'];
$arr[$i]['data'][$j]['data'][$k]['name'] = $row['iname'];
break;
case $row['c2name'] != $c2name :
$j++;
$k = 0;
$arr[$i]['data'][$j]['name'] = $row['c2name'];
$arr[$i]['data'][$j]['data'][$k]['name'] = $row['iname'];
break;
default :
$k++;
$arr[$i]['data'][$j]['data'][$k]['name'] = $row['iname'];
break;
}
$c1name = $row['c1name'];
$c2name = $row['c2name'];
$iname = $row['iname'];
}
除此之外,还有一些用于生成菜单的代码。只有2个级别,它最初编码为第一级的一个查询,然后对第一级中的每个记录进行一次查询以获取其下的所有项目。并不复杂(第一级只有约16项,平均每项不足10项)。我把它重写为一个加入的查询。生成该菜单的典型时间从0.25秒下降到0.004秒。将查询发送到数据库的时间很容易过快。