mysql示例如下http://sqlfiddle.com/#!9/68653/2
Mysql表(命名为topics
)
TopicId | TopicName | ClosestUpperLevelId
--------------------------------------------
1 | Books | 0
2 | BooksAboutCss | 1
3 | BooksAboutHtml | 1
4 | BooksAboutCss1 | 2
5 | BooksAboutCss2 | 2
6 | BooksAboutHtml1 | 3
7 | BooksAboutHtml2 | 3
8 | E-Books | 0
9 | Magazines | 0
对于顶级主题,ClosestUpperLevelId
为0。对于子主题,ClosestUpperLevelId
是最接近上级主题的TopicId
(TopicId - ClosestUpperLevelId)
Books (1-0)
BooksAboutCss (2-1)
BooksAboutCss1 (4-2)
BooksAboutCss2 (5-2)
BooksAboutHtml (3-1)
BooksAboutHtml1 (6-3)
BooksAboutHtml2 (7-3)
E-Books (8-0)
Magazines (9-0)
例如,我创建了一个页面,页面的位置是domain.com/Books/BooksAboutCss/BooksAboutCss2
现在我决定编辑这个页面。例如,我想编辑页面的位置(主题或类别),并将其设置为domain.com/Magazines
。所以我需要获取所有主题,与现有(保存的)页面相关。然后将为每组(级别)主题创建选择框。
目前尝试使用phpwhile
并多次连接到mysql获取数据。就像下面的代码如果没有php while
,我怎么能得到同样的结果?如何只连接一次mysql并获取所有必要的数据?我需要使用mysql while
吗https://dev.mysql.com/doc/refman/5.1/en/while.html?
$topic_names_1[0]['UpperLevelNumberRenamed'] = 5;//just set some value to start to fetch
while ( trim($topic_names_1[0]['ClosestUpperLevelId']) != 0 ){
try {
$stmt_1 = $db->prepare('
SELECT `TopicId`, `TopicName`, `ClosestUpperLevelId`
FROM `topics`
WHERE `ClosestUpperLevelId` =
(
SELECT `ClosestUpperLevelId`
FROM `topics`
WHERE `TopicId` = ?
)
;');
$stmt_1->execute( array( trim($topic_names_1[0]['UpperLevelNumberRenamed']) ) );
$topic_names_1 = $stmt_1->fetchAll(PDO::FETCH_ASSOC);
echo '<pre>', print_r($topic_names_1), ' topic_names_1 __</pre>';
}//try {
catch (PDOException $e){
echo "<br> stmt_1 DataBase Error: " .htmlspecialchars( $e->getMessage() , ENT_QUOTES, "UTF-8").'<br>';
}
catch (Exception $e) {
echo " stmt_1 General Error: ".htmlspecialchars( $e->getMessage() ).'<br>';
}
}//while ( trim($topic_names[0]['UpperLevelNumberRenamed']) != 0 )
结果得到像这样的阵列
Array
(
[0] => Array
(
[TopicId] => 4
[TopicName] => BooksAboutCss1
[ClosestUpperLevelId] => 2
)
[1] => Array
(
[TopicId] => 5
[TopicName] => BooksAboutCss2
[ClosestUpperLevelId] => 2
)
)
1 topic_names_1 __
Array
(
[0] => Array
(
[TopicId] => 2
[TopicName] => BooksAboutCss
[ClosestUpperLevelId] => 1
)
[1] => Array
(
[TopicId] => 3
[TopicName] => BooksAboutHtml
[ClosestUpperLevelId] => 1
)
)
1 topic_names_1 __
Array
(
[0] => Array
(
[TopicId] => 1
[TopicName] => Books
[ClosestUpperLevelId] => 0
)
[1] => Array
(
[TopicId] => 8
[TopicName] => E-Books
[ClosestUpperLevelId] => 0
)
[2] => Array
(
[TopicId] => 9
[TopicName] => Magazines
[ClosestUpperLevelId] => 0
)
)
1 topic_names_1 __
更新
用mysql while
找到一个例子。尝试创建自己的代码
创建此
SET `ClosestUpperLevelId` := 2;
WHILE `ClosestUpperLevelId` > 0
DO
SELECT `TopicId`, `TopicName`, `ClosestUpperLevelId`;
END WHILE;
这个(http://sqlfiddle.com/#!9/68653/7)
CREATE PROCEDURE dowhile()
BEGIN
DECLARE `ClosestUpperLevelId` INT DEFAULT 2;
WHILE `ClosestUpperLevelId` > 0 DO
SELECT `TopicId`, `TopicName`, `ClosestUpperLevelId`;
END WHILE;
END;
出现错误。。。
您可以将select语句移到while循环之前,并从where子句中取出topic_id
。然后在循环中使用数组搜索函数或类似函数从完整的记录集中检索。通过运行相同的查询一次,您的dB将能够缓存结果
MySQL这样的关系数据库天生不擅长存储分层数据,但有很多方法可以做到这一点。我知道的两种方法是"邻接列表"answers"嵌套集"。
对于邻接列表,只需为每一行存储一个"parent_id"字段。根行(没有父行)的parent_id字段只能为NULL。相邻列表很容易管理,但不是很灵活,并且需要递归查询来找到从根到叶的路径(除非你只深入两个级别,否则你可以简单地加入)。
这里有一个例子:
id | parent_id | name
0 NULL grandfather
1 0 father
2 1 grandson
3 1 granddaughter
此查询将有助于收集数据:
SELECT * FROM
`people` AS p1
JOIN `people` p2
ON p1.id = p2.parent_id
超过这两个级别,就需要递归。或者,您也可以查询整个表并将其汇编成代码。
嵌套集稍微复杂一点,但允许您轻松地向树上查询给定的叶节点。一开始,通过查看可视化来理解嵌套集要容易得多,请查看以下内容:
https://en.wikipedia.org/wiki/Nested_set_model
下面是您的模式:
left | right | name
0 7 grandfather
1 6 father
2 3 grandson
4 5 granddaughter
这里有一个吸引父亲和孩子的例子:
SELECT *
FROM `people`
WHERE `left` >= 1 AND `right` <= 6
嵌套集的缺点是,当层次结构发生变化时,需要更新整个表的left
和right
值。
谷歌"在mysql中管理分层数据"获取更多信息。我希望这能有所帮助。