仅在一个 SQL 查询中检索所有类别、子类别、子子类别等的完整列表

Posted

技术标签:

【中文标题】仅在一个 SQL 查询中检索所有类别、子类别、子子类别等的完整列表【英文标题】:Retrieve a complete list of all Categories, Sub Categories, Sub Sub Categories, etc. in only one SQL query 【发布时间】:2009-07-23 06:03:26 【问题描述】:

我在 mysql 中有以下表结构和数据

CatID  CatName     ParentCatID
-------------------------------
1       Shirts        NULL
2       Short Sleev    1
3       Long Sleev     1
4       Collarless     2
5       Collar         2
6       Collarless     3
7       Collar         3
8       Square Cut     4
9       Round Cut      4
10      Square Cut     6
11      Round Cut      6

我想要的返回数据是这样的:

Shirts > Short Sleev
Shirts > Long Sleev
Shirts > Short Sleev > Collarless
Shirts > Short Sleev > Collar
Shirts > Long Sleev > Collarless
Shirts > Long Sleev > Collar
Shirts > Short Sleev > Collarless > Square Cut
Shirts > Short Sleev > Collarless > Round Cut
Shirts > Short Sleev > Collar > Square Cut
Shirts > Short Sleev > Collar > Round Cut

我们如何在 MySQL 中使用一个 SQL 查询来获取这些数据?

【问题讨论】:

您知道您的数据库中有拼写错误吗?它是“袖子”和“颜色”。 嗯,我看到我拼错了 Sleeve and Collar 和 Collarless。感谢您指出。未更正。 【参考方案1】:

不是一个真正的答案,但我过去在 php 中使用的一个肮脏的修复是这样的:

$categories = array();

$sql = "SELECT CatID, CatName, ParentCatID FROM TableName";
$res = mysql_query($sql);
while ($row = mysql_fetch_assoc($res)) 
    $parent = intval($row['ParentCatId']);
    if (!isset($categories[$parent])) 
        $categories[$parent] = array();
    
    $categories[$parent][] = $row;

这将为您提供一系列类别和子类别,您可以使用递归函数对其进行迭代。比如:

function build_categories($parent, $categories) 
    if (isset($categories[$parent]) && count($categories[$parent])) 
        echo '<ul>';
        foreach ($categories[$parent] as $category) 
            echo '<li><a href="#">' . $category['CatName'] . '</a>';
            echo build_categories($category['id'], $categories);
            echo '</li>';
        
        echo '</ul>';
    

$menu = build_categories(0, $categories);

【讨论】:

【参考方案2】:

查看Managing Hierarchical Data in MySQL 和Storing Hierarchical Data in a Database。

【讨论】:

感谢您的链接。我会检查出来的。 您能否将这些文章的精髓添加到您的答案中?在目前的形式中,它只不过是一条评论。【参考方案3】:

我需要它作为具有层次结构的下拉列表。所以我使用了上面的代码并做了一些更改。结果符合我的要求。我想把这个分享给你。

$category_string = "";
function build_categories_options($parent, $categories, $level) 
    global $category_string;
    if (isset($categories[$parent]) && count($categories[$parent])) 
        $level .= " - ";
        foreach ($categories[$parent] as $category) 
            $opt_value = substr($level.$category['CatName'],3);
            $category_string .= '<option value="'.$category['CatID'].'">'.$opt_value.'</option>';
            build_categories_options($category['CatID'], $categories, $level);
        
        $level = substr($level, -3);
    
    return $category_string;

$category_options = build_categories_options(0, $categories, '');
$category_options = '<select name="sel_category" id="sel_category">'.$category_options.'</select>';

然后使用 echo 语句在页面的任何位置打印。

<?php echo $category_options; ?>

【讨论】:

感谢您提供此示例。我已经实现了递归算法来检索包含所有子类别的类别列表,但我希望在数据库级别执行此操作,以便 MySQL 将在一个简单的查询中返回列表,或者我们可以定义一个返回完整列表的视图。 【参考方案4】:

我认为 MySQL 不支持树状结构(例如,与 Oracle 相反)。

如果你知道你的树的最大深度,你可以用连接做一些事情......如果你不知道,那就更难了。

例如,您可以查看文章Managing Hierarchical Data in MySQL。

如果您的表格中只有几行,一个可能好的解决方案是只使用“select *”,并在 PHP 中处理所有这些。

【讨论】:

这正是我们目前正在做的事情。但是如果可能的话,我希望自己免于维护这些额外的 PHP 代码的麻烦。

以上是关于仅在一个 SQL 查询中检索所有类别、子类别、子子类别等的完整列表的主要内容,如果未能解决你的问题,请参考以下文章

获取所有类别(多级)

SQL LEFT JOIN 到许多类别

sql 查询以检索Magento中的所有产品ID及其所属的类别。

扩展嵌套项 FastAdapter

不允许聚合聚合 Bigquery

woocommerce-如何仅在商店页面上显示子类别?