只是为了学习 SQL,我想用一个简单的父子创建一个层次结构。就像堆栈溢出徽章( parent :问题徽章, child :利他主义者)。
这是我的sql:
SELECT *
FROM (`badge_types`)
LEFT JOIN `badges` ON `badges`.`badge_type` = `badge_types`.`badge_type_id`
这是我得到的:
(
[0] => stdClass Object
(
[badge_type_id] => 2
[badge_type_title] => Participation Badges
[badge_type_description] => Badges earning by participating in various areas of the site.
[badge_type_order] => 2
[badge_id] => 1
[badge_name] => Autobiographer
[badge_level] => 3
[badge_requirement] => Completed all user profile fields
[badge_type] => 2
[badge_order] => 1
[badge_sites] => 0
)
[1] => stdClass Object
(
[badge_type_id] => 1
[badge_type_title] => Experience Badges
[badge_type_description] => Badges earned by amount of experience gain throughout the site.
[badge_type_order] => 1
[badge_id] => 2
[badge_name] => Apprentice
[badge_level] => 3
[badge_requirement] => Achieved 500 experience
[badge_type] => 1
[badge_order] => 1
[badge_sites] => 0
)
)
我怎样才能把它变成:
array(
array(
[badge_type_id] => 2
[badge_type_title] => Participation Badges
[badge_type_description] => Badges earning by participating in various areas of the site.
[badge_type_order] => 2
[badges] => array(
array(
[badge_id] => 1
[badge_name] => Autobiographer
[badge_level] => 3
[badge_requirement] => Completed all user profile fields
[badge_type] => 2
[badge_order] => 1
[badge_sites] => 0
),
array(
[badge_id] => 2
[badge_name] => Example 2
[badge_level] => 3
[badge_requirement] => blah bla
[badge_type] => 2
[badge_order] => 1
[badge_sites] => 0
)
)
),
array(
[badge_type_id] => 1
[badge_type_title] => Experience Badges
[badge_type_description] => Badges earned by amount of experience gain throughout the site.
[badge_type_order] => 1
[badges] => array(
array(
[badge_id] => 2
[badge_name] => Apprentice
[badge_level] => 3
[badge_requirement] => Achieved 500 experience
[badge_type] => 1
[badge_order] => 1
[badge_sites] => 0
),
array(
[badge_id] => 2
[badge_name] => Example 2
[badge_level] => 3
[badge_requirement] => Achieved 1000 experience
[badge_type] => 1
[badge_order] => 1
[badge_sites] => 0
)
)
)
)
我可以使用多个 MySQL 查询来做到这一点,但理想情况下我只想使用一个查询(如果可能的话)?
最佳答案
用 SQL 查询不可能实现这一点,因为(由于关系模型的性质)SQL 查询将始终返回没有任何嵌套的“扁平”结果集(极少数异常(exception)是供应商 SQL 扩展,目标是生成 XML 输出或类似的,但 MySQL 没有这样的扩展)。
如果您想从 SQL 结果集中获取嵌套数组,则必须使用 PHP 代码对其进行后处理。这段代码的组织方式类似于对数组的分组循环(使用 SQL 预排序),每次“内部”表的键更改时都会启动新组。这可以在 PHP 中以相当通用的方式完成,因此您可以编写一个这样的函数来后处理许多 SQL 查询(为其提供适当的参数)。
ADDITION 下面是这样一个函数:
function groupnest( $data, $groupkey, $nestname, $innerkey ) {
$outer0 = array();
$group = array(); $nested = array();
foreach( $data as $row ) {
$outer = array();
while( list($k,$v) = each($row) ) {
if( $k==$innerkey ) break;
$outer[$k] = $v;
}
$inner = array( $innerkey => $v );
while( list($k,$v) = each($row) ) {
if( $k==$innerkey ) break;
$inner[$k] = $v;
}
if( count($outer0) and $outer[$groupkey]!=$outer0[$groupkey] ) {
$outer0[$nestname] = $group;
$nested[] = $outer0;
$group = array();
}
$outer0 = $outer;
$group[] = $inner;
}
$outer[$nestname] = $group;
$nested[] = $outer;
return $nested;
}
data
是要嵌套的数组(SQL结果集),
groupkey
是“外部”实体主键的列名,
nestname
是将放置“内部行”的字段的名称,
innerkey
是“内部”实体主键的列名。
在结果集中,“外部”实体的所有列都必须在 $innerkey
列之前,并且“内部”实体的所有列都必须在它之后。
要正确分组,结果集必须首先按来自“外部”实体的唯一 表达式排序,例如按 badge_type_title、badge_type_id、...排序
。 order by
中的后续字段将定义“内部”组内的排序。
要嵌套连接 3 个或更多实体,您可以多次使用此函数(折叠“从内到外”)
关于php - MySQL中的层次结构数据到PHP多维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19604447/