与php不同,while循环和到mysql的多个连接只需要连接一次


Instead of php while loop and multiple connections to mysql want to connect only once

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

嵌套集的缺点是,当层次结构发生变化时,需要更新整个表的leftright值。

谷歌"在mysql中管理分层数据"获取更多信息。我希望这能有所帮助。