mysql多级分类设计

news2024/12/28 4:13:09

简介

在数据库设计中,经常会遇到需要存储多级分类信息的情况,如商品分类、地区分类等。本文将详细介绍如何在MySQL中设计和管理多级分类数据

解决方案

一. 层级字段(Hierarchy Field)方法

层级字段方法是最常见和简单的多级分类设计方法之一。它通过在分类表中添加一个表示层级关系的字段来实现。每个分类记录包含一个字段来表示其父级分类的ID

数据表结构

CREATE TABLE categories (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    parent_id INT,
    level INT
);
  • id:分类ID,作为主键
  • name:分类名称
  • parent_id:父级分类的ID
  • level:分类所处的层级

数据插入

在向分类表中插入数据时,我们可以根据父级分类的ID来设置相应的层级字段和层级信息。

例如,插入三级分类数据的示例:

INSERT INTO categories (id, name, parent_id, level) VALUES
(1, '电子产品', NULL, 1),
(2, '手机', 1, 2),
(3, '平板电脑', 1, 2),
(4, '苹果手机', 2, 3),
(5, '华为手机', 2, 3),
(6, 'iPad', 3, 3),
(7, '安卓平板', 3, 3);

查询分类

使用层级字段方法,可以轻松地进行分类的查询。例如,要获取所有二级分类的手机列表,可以执行以下查询:

SELECT * FROM categories WHERE level = 2 AND parent_id = 1;

层级字段方法的优缺点

优点:
  • 简单直观,易于理解和实现
  • 查询和操作单个层级的分类很高效
缺点:
  • 难以处理复杂的层级关系,如循环引用或动态变化的层级
  • 查询多级分类和递归操作时,性能可能受到影响
  • 从根节点进行递归查询,时间复杂度是 O(n)

二. MPTT预排序算法

什么是MPTT算法?

MPTT算法是一种用于处理树状结构数据的算法,其中MPTT代表Modified Preorder Tree Traversal(修改的先序遍历树遍历)。它通过为树中的每个节点分配一个预排序值来组织和表示树的结构。这种预排序值允许我们以一维的方式存储和操作树,同时保持树的层次结构和父子关系。
MPTT 正是为了解决多层级关系数据的查询效率问题,它的时间复杂度竟然能高效到一个常量,即 O(1)

MPTT算法的原理

MPTT算法的原理很简单,它通过以下几个步骤来为树节点分配预排序值:

  1. 初始化左值和右值为1
  2. 对树进行深度优先搜索(DFS)的先序遍历
  3. 遍历到一个节点时,将该节点的左值设为当前左值,并将当前左值加1
  4. 递归处理节点的每个子节点
  5. 当处理完所有子节点后,将节点的右值设为当前左值,并将当前左值加1

通过这个过程,我们可以为每个节点分配唯一的左值和右值,从而形成树的预排序遍历结构。

MPTT分析

以下是django-mptt模块定义的一个部门

from mptt.models import MPTTModel, TreeForeignKey
class Department(MPTTModel):
    """组织"""

    name = models.CharField("组织名称", max_length=255)
    # 部门标识,不同于自增 id,多数情况存储各个公司组织架构系统的id, 非必须
    code = models.CharField("组织标识", null=True, blank=True, unique=True, max_length=64)
    parent = TreeForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, related_name="children")
    order = models.IntegerField("顺序", default=1)
    profiles = models.ManyToManyField(Profile, blank=True, related_name="departments", verbose_name="成员")
    enabled = models.BooleanField("是否启用", default=True)
    extras = JSONField("额外信息", default={})

    category_id = models.IntegerField("用户目录ID", null=True, blank=True)

    class Meta:
        ordering = ["id"]
        verbose_name = "组织表"
        verbose_name_plural = "组织表"

        index_together = [
            ["tree_id", "lft", "rght"],
            ["parent_id", "tree_id", "lft"],
        ]

在上述代码中,在进行数据库迁移后,数据库里面额外多出了 5个字段,分别是: lft、rgt、level、tree_id、parent_id。
这些多出来的字段就是为了定义树的结构和层级。下面我们就来分析一下,每个字段的作用是什么

  • tree_id:树的 id,用来区分数据库中众多树的某一颗树。
  • level:一颗标准的树会有高度、深度、层级,根节点的层级是 1,子节点的层级是父节点层级加 1
  • parent_id:父 id,节点的父级 id,根节点没有父节点,所以值为 NULL
  • lft:节点左值
  • rgt:节点右值。

树结构如下:
在这里插入图片描述

在这里插入图片描述

查询

  • 遍历整棵树:
    遍历整棵树只需要查找 tree_id 等于 1 的条件即可

  • 某节点下所有的子孙节点:
    查找节点 4 的所有子孙节点,以 4 作为参考点。左值大于 6 且右值小于 11 的所有子孙节点,就是节点 4 的所有子孙节点。

  • 找到某节点下所有的子节点
    查找节点 1 的所有子节点,以 1 作为参考点。tree_id 等于 1 且 level 等于 2

  • 查找某节点的路径
    查找节点 9 的所有上级路径,以 9 作为参考点。左值小于 14 且右值大于 15 的所有节点,就是节点 ``9的路径。结果是:1 -> 7 -> 8 -> 9`。

新增

MPTT 在遍历的时候很快,但是其他的操作就会变得很慢,所以使用 MPTT 要尽量避免查询之外的其他操作,这是因为节点在插入、更新(移动)、删除会破坏树的平衡。所以在做这些操作的时候需要对数进行调整,达到新的平衡

以新增节点操作为例,算法可分解为以下几个步骤:

  • 如果要在不存在的树中新增节点,即要创建一颗新树。那么它是没有 parent_id 的,所以 parent_id 值为 NULL,level 是 1,tree_id 是根据已有树的最大 tree_id 加 1
  • 如果要在已存在的树中新增节点。那么它的 parent_id 是父节点的 id,level 是父节点的 level 加 1,tree_id 和父节点保持一致。
  • 修复被破坏平衡的其他节点的左值。大于 parent_id 右值的所有节点的左值加 2
  • 修复被破坏平衡的其他节点的右值。大于等于 parent_id 右值的所有节点的右值加 2

删除

和增加类似,只不过删除一个节点以后对左值和右值进行相反的操作,即减 2

更新

更新(移动)其实就是删除一个老节点,再新增一个新节点,具体算法参考上面的例子

MPTT预排序算法优缺点

优点:
  • 查询操作较多的场景,查询的效率不受分类层级的增加的影响,为o(1)
缺点:
  • 随着数据的增多,每增删数据,都要同时操作多条受影响数据,执行效率逐渐下降

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/601004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用redis的消息订阅功能更新应用内的caffeine本地缓存

1、为什么要更新caffeine缓存? 1.1,caffeine缓存的优点和缺点 生产环境中,caffeine缓存是我们在应用中使用的本地缓存, 它的优势在于存在于应用内,访问速度最快,通常都不到1ms就能做出响应, 缺…

Gitlab数据自动备

【场景】:将Gitlab服务器定时备份到Gitlab备份服务器 1.设置Gitlab服务器以及Gitlab备份服务器时间 1.1查看系统时间: date 1.2修改具体时间: date -s "2023-06-02 15:15:00" 1.3把时间写入CMOS: clock -w 1.4把…

深入了解Altium Designer 2023的规则设置

在PCB设计中,规则设置是确保PCB设计符合标准和规范的关键步骤,Altium Designer 2023作为一款强大的PCB设计软件,提供了丰富的规则设置功能,可帮助电子工程师实现高效准确的设计。下面将详细介绍AD 2023中的规则设置功能&#xff0…

【OpenMMLab AI实战营第二期笔记】人体关键点检测与MMPose

人体关键点检测与MMPose 介绍 人体姿态估计(Human Pose Estimation)是计算机视觉领域中的一个重要研究方向,也是计算机理解人类动作、行为必不可少的一步,人体姿态估计是指通过计算机算法在图像或视频中定位人体关键点&#xff…

TDEngine3.0环境搭建总结

TDEngine3.0环境搭建总结 一、TDengine 介绍二、TDengine的下载三、TDengine Server安装及配置3.1 安装3.2 taos的参数配置3.3 启动3.4 taosAdapter 四、TDengine Client 安装4.1 linux客户端安装4.2 windows客户端安装 一、TDengine 介绍 TDengine 官网 TDengine的介绍   T…

算法工程师的岗位职责(合集)

算法工程师的岗位职责1 职责: 1、负责运动控制的数据采集、信号处理、仪器控制等模块研发和维护,包括关键技术方案设计/详细设计/调试/验证/测试/现场调试 2、编写软件使用说明书等相关技术性文件 3、完成项目中有关机器人轨迹设计、分析、控制的需求分析(7轴机械手…

Maven依赖传递

Maven 依赖传递是 Maven 的核心机制之一,它能够一定程度上简化 Maven 的依赖配置。本节我们将详细介绍依赖传递及其相关概念。 依赖传递 如下图所示,项目 A 依赖于项目 B,B 又依赖于项目 C,此时 B 是 A 的直接依赖,C…

java爬虫详解及简单实例

java爬虫是一种自动化程序,可以模拟人类在互联网上的行为,从网站上抓取数据并进行处理。下面是Java爬虫的详细解释: 1、爬虫的基本原理 Java爬虫的基本原理是通过HTTP协议模拟浏览器发送请求,获取网页的HTML代码,然后…

PS2024后期调色滤镜插件Alien Skin Exposure7

Exposure是一款常见的ps调色滤镜插件,相信许多朋友都曾经用过它。一张普通的图片经过后期调色处理后,可以得到更加靓丽的效果。因此选择一款专业性强、操作简单的后期调色软件很重要。那么,我们应该如何选择后期调色软件呢?下面给…

第三大章docker的部署

1. 红为写的命令 systemctl stop firewalld.service setenforce 0 #安装依赖包yum install -y yum-utils device-mapper-persistent-data lvm2 -------------------------------------------------------------------------------------------- yum-utils:提供了…

揭秘虚拟直播:3D场景与2D背景的区别

虚拟直播是指通过技术手段创造出虚拟场景,将主播或演员放置其中进行实时直播的一种形式。这种直播方式结合了虚拟现实(VR)、增强现实(AR)和实时渲染等技术,近年来,随着VR和AR技术的不断成熟和普…

Flink第八章:FlinkSQL

系列文章目录 Flink第一章:环境搭建 Flink第二章:基本操作. Flink第三章:基本操作(二) Flink第四章:水位线和窗口 Flink第五章:处理函数 Flink第六章:多流操作 Flink第七章:状态编程 Flink第八章:FlinkSQL 文章目录 系列文章目录前言一、常用函数1.快速上手案例2.连接外部数据…

chatgpt赋能python:Python岗位需求日渐增加

Python岗位需求日渐增加 Python编程语言在当前的IT行业中越来越受欢迎。其灵活性和易用性使得Python在各种领域中使用广泛,比如Web开发、数据科学、人工智能等。作为一名有10年Python编程经验的工程师,我认为Python是一种非常有前途的编程语言&#xff…

IDC MarketScape《决策支持分析数据平台供应商评估》报告发布,亚马逊云科技位列“领导者”

随着科学技术的不断发展,人们的生活方式也在不断改变。现在,人们可以通过互联网获得更多的信息,也可以通过智能手机随时随地与他人进行交流。此外,人工智能技术的进步也使得机器能够完成一些复杂的任务,从而提高了人们…

重磅新品 | 立仪发布高速版嵌入式光谱共焦G系列

重磅新品 | 立仪发布高速版嵌入式光谱共焦G系列 立仪科技作为国产光谱共焦技术的引领者,在光谱共焦技术上数年磨一剑,打破封锁,而此次研发出的嵌入式光谱共焦位移传感器G系列采用先进的FPGACPU硬件架构等技术自研而成并结合高强度LED光源、创…

python---变量和简单的数据类型

python---变量和简单的数据类型 1. 变量的命名2. 字符串2.1 使用方法修改字符串的大小写2.2 合并(拼接)字符串2.3 使用制表符或换行符来添加空白2.4 删除空白2.5 使用字符串时避免使用语法错误 3. 数字3.1 整数3.2 浮点数3.3 使用函数str()避免类型错误 …

基于springboot地方旅游系统的设计与实现

摘 要 本次设计内容是基于Springboot的旅游系统的设计与实现,采用B/S三层架构分别是Web表现层、Service业务层、Dao数据访问层,并使用Springboot,MyBatis二大框架整合开发服务器端,前端使用vue,elementUI技术&…

vue-admin-template刷新侧边栏数据丢失

使用vue-admin-template时,刷新页面侧边栏消失😒,仔细查看代码后找到原因,使用的路由与vuex有关,而在刷新页面时vue会重新加载vue实例,vuex中的数据会被初始化,所以看不到侧边栏是因为数据被重置…

虚拟现实 VR 智慧办公室可视化

“虚拟现实”是来自英文“Virtual Reality”,简称 VR 技术,其是通过利用计算机仿真系统模拟外界环境,主要模拟对象有环境、技能、传感设备和感知等,为用户提供多信息、三维动态、交互式的仿真体验。 图扑软件基于自研可视化引擎 H…

containerd 容器概述

containerd 容器概述 官方文档: https://containerd.io在 2016 年 12 月 14 日,Docker 公司宣布将 containerd 从 Docker 中分离,由开源社区独立发展和 运营。Containerd 完全可以单独运行并管理容器,而 Containerd 的主要职责是镜像管理和…