不用递归SQL的无限级分类

在很多时候,我们会用到无限级分类,但是在子分类很多的时候,简单的递归可能会产生很多的SQL查询,这非常消耗性能。所以想了一个不递归SQL的无限级分类的实现。

简单的递归无限级分类,是使用 parent_id 来标识出当前分类的父级分类,这样为了获取到所有子集分类就必须递归查询。如果把它更改为 parent_path 存储当前分类的完整父级分类路径,就可以不使用递归,通过简单的查询得到所有子集分类了。

Table:

CREATE TABLE `channel` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `parent_path` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `channel_path_index` (`parent_path`)
);
INSERT INTO `channel` VALUES (1, '1', '');
INSERT INTO `channel` VALUES (2, '2', '');
INSERT INTO `channel` VALUES (3, '3', '');
INSERT INTO `channel` VALUES (4, '1-1', ':1:');
INSERT INTO `channel` VALUES (5, '1-1-1', ':1:4:');
INSERT INTO `channel` VALUES (6, '1-1-1-1', ':1:4:5:');
INSERT INTO `channel` VALUES (7, '1-1-1-2', ':1:4:5:');
INSERT INTO `channel` VALUES (8, '1-1-1-1-1', ':1:4:5:6:');
INSERT INTO `channel` VALUES (9, '2-1', ':2:');
INSERT INTO `channel` VALUES (10, '2-2', ':2:');
INSERT INTO `channel` VALUES (11, '2-2-1', ':2:10:');

Code:

// 连接测试数据库
$con = mysql_connect('localhost', 'root', '');
mysql_select_db('test');

// 封装的测试方法
function get_channel($id, $self = false)
{
    $sql = "SELECT * FROM channel WHERE parent_path LIKE '%:{$id}:%'";
    if ($self) {
        $sql .= " OR id = {$id}";
    }
    $query = mysql_query($sql);
    $data = array();
    while ($row = mysql_fetch_assoc($query)) {
        $data[] = $row;
    }
    return $data;
}

// 获取id为4的所有子集分类,不包含当前分类。
var_dump(get_channel(4));
// 获取id为4的所有子集分类,包含当前分类。
var_dump(get_channel(4, true));

发表评论