MySQL之无限级分类表设计

本文详细讲解了无限分级表的设计方法,通过创建包含层级关系的商品类型表,并演示了如何通过自身连接查询子类及其父类。此外,还介绍了如何利用多表删除语法高效地处理数据库中的重复记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

首先查找一下goods_cates表和table_goods_brands数据表

分别使用命令:

root@localhost test>show columns from goods_cates;
root@localhost test>select * from goods_cates;

 


1、无限分级表设计
但这仅仅是示例,远远达不到实际的需求,比如说书籍这个类,在网站上可以搜索到在书籍这个分类下面还有历史,文学,经济等等子类,子类下面还有子类,这种无限分类如何设计呢?理论上可以设计很多张表,随着分类的增多,这些数据表不可能无限扩展,因此可以通过如下设计:

CREATE TABLE table_goods_type(
    type_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
type_name VARCHAR(20) NOT NULL,
parent_id SMALLINT UNSIGNED NOT NULL DEFAULT 0
);
创建成功之后查看一下

root@localhost test>show columns from table_goods_type;

 


现在插入若干条记录

INSERT table_goods_type(type_name,parent_id) VALUES ('家用电器',DEFAULT);
INSERT table_goods_type(type_name,parent_id) VALUES ('电脑办公',DEFAULT);
INSERT table_goods_type(type_name,parent_id) VALUES ('大家电',1);
INSERT table_goods_type(type_name,parent_id) VALUES ('生活电器',1);
INSERT table_goods_type(type_name,parent_id) VALUES ('平板电视',3);
INSERT table_goods_type(type_name,parent_id) VALUES ('空调',3);
INSERT table_goods_type(type_name,parent_id) VALUES ('电风扇',4);
INSERT table_goods_type(type_name,parent_id) VALUES ('饮水机',4);
INSERT table_goods_type(type_name,parent_id) VALUES ('电脑整机',2);
INSERT table_goods_type(type_name,parent_id) VALUES ('电脑配件',2);
INSERT table_goods_type(type_name,parent_id) VALUES ('笔记本',9);
INSERT table_goods_type(type_name,parent_id) VALUES ('超极本',9);
INSERT table_goods_type(type_name,parent_id) VALUES ('游戏本',9);
INSERT table_goods_type(type_name,parent_id) VALUES ('CPU',10);
INSERT table_goods_type(type_name,parent_id) VALUES ('主机',10);
 查询一下记录
root@localhost test>select * from table_goods_type;

 


关于parent_id的说明:

1、parent_id为0,家用电器为顶级结点,意味着就是没有父亲结点,因此就是为0,同电脑办公也是父亲节点

2、大家电作为家用电器的子类,所以其父类为家用电器的type_id,所以写的是1,同生活电器

3、而平板电视属于大家电的子类,因此其parent_id为3,同样饮水机属于生活电器,因此parent_id为4,依次类推

上述的表设计好了之后如何做查找呢?

要做查找的话就需要通过自身连接来实现,所谓自身连接就是数据连接并不是其他数据表,而是自身。

现在想查找所有的子类和其父类,如何操作呢?要是有两张表,可以很容易知道,但是现在一张表怎么实现呢,想象右侧也有一张表,这张表示子表

   

 

因为子表中的parent_id指向的是父表中的type_id

root@localhost test> SELECT son.type_id,son.type_name,parent.type_name FROM table_goods_type AS son
-> LEFT JOIN table_goods_type AS parent
-> ON son.parent_id = parent.type_id;

 


因为家电电器和电脑办公属于顶级分类,因此其没有父类,其它的均可以查找到父类,因为MySQL没有递归查询的能力,因此只能查找到一级分类。既然能查到子类的id(type_id),子类的名字name(type_name)和父类的名字type_name. 

root@localhost test>SELECT parent.type_id,parent.type_name,son.type_name FROM table_goods_type parent LEFT JOIN
-> table_goods_type son ON son.parent_id = parent.type_id;

 


这样就查到了左边和右边两个类,左边是家用电器这个类,其子类有大家电和生活电器,大家电下面有子类平板电视和空调,依次类推,当然像主机、CPU下面就没有子类,所以为NULL。由于左边的父类显示有重复的,这里进行修改

root@localhost test>SELECT parent.type_id,parent.type_name,son.type_name FROM table_goods_type parent LEFT JOIN
-> table_goods_type son ON son.parent_id = parent.type_id GROUP BY parent.type_name;

 


root@localhost test>SELECT parent.type_id,parent.type_name,son.type_name FROM table_goods_type parent LEFT JOIN
-> table_goods_type son ON son.parent_id = parent.type_id GROUP BY parent.type_name
-> ORDER BY parent.type_id;

 

 


现在只显示子类的数目,不显示子类的名字

root@localhost test>SELECT parent.type_id,parent.type_name,count(son.type_name) child_count FROM table_goods_type parent LEFT JOIN
-> table_goods_type son ON son.parent_id = parent.type_id GROUP BY parent.type_name
-> ORDER BY parent.type_id;

 


这样就只显示了子类的数量

2、多表的删除
多表的删除的语法结构是

DELETE table_name[.*] [,table_name[.*]]... FROM table_references [WHERE where_condition]

 


在表goods中发现有两条重复的记录,分别是honorX6和Laserjet Pro P16重复,可能在有意无意键录入了重复的记录,现在想删除重复的记录,保留goods_id较小的那个,这就是通过多表删除实现,采用一张表模拟两张表的方法实现,首先要查找重复的记录。

root@localhost test>SELECT goods_id,goods_name FROM goods GROUP BY goods_name;

 


总共11条记录,现在分组筛选之后还有9条,说明重复了2条,但是只想要记录重复(超过两个以上的),因此可以是HAVING

root@localhost test>SELECT goods_id,goods_name FROM goods GROUP BY goods_name HAVING count(goods_name) >= 2;

 


这两条记录就是重复的,就是需要删除的,因此可以参照这张表删除初始的表goods    

root@localhost test>DELETE t1 FROM goods AS t1 LEFT JOIN (SELECT goods_id,goods_name FROM goods GROUP BY
-> goods_name HAVING count(goods_name) >= 2) AS t2 ON t1.goods_name = t2.goods_name WHERE t1.goods_id > t2.goods_id;

 


提示两条记录被删除,再来查看一下表goods

 


原文:https://blog.youkuaiyun.com/rhx_qiuzhi/article/details/79936575

转载于:https://www.cnblogs.com/ivy-zheng/p/11289608.html

编写手机类(MobilePhone),含有type(型号,String类型)、price(价格,int类型)属性,要求该类实现Comparable接口,重写compareTo方法,实现按照price的大小来确定两个手机对象的大小关系。 在链表中添加三个手机对象(从键盘输入),通过Collections类的sort方法对链表中的对象按照price升序排序。输入第四个手机对象的信息,并查找它的price是否与链表中某个对象的price相同。 输入格式: 先输入三部手机的型号、价格信息 再输入要查找的第四部手机的型号、价格信息 每部手机信息的格式如:Redmi9A 599 输出格式: 先输出三部手机排序前的信息 再输出三部手机排序后的信息 最后输出第四部手机是否与前面某部手机价格相同 具体格式参考输出样例 输入样例1: 在这里给出一组输入,第四部手机与前三部中某一部价格相同。例如: HONOR70 2699 MI12 3499 VIVOS15 3299 RedmiK50 2699 输出样例1: 在这里给出相应的输出,第四部手机与前三部中某一部价格相同。例如: 排序前,链表中的数据: 型号:HONOR70,价格:2699 型号:MI12,价格:3499 型号:VIVOS15,价格:3299 排序后,链表中的数据: 型号:HONOR70,价格:2699 型号:VIVOS15,价格:3299 型号:MI12,价格:3499 RedmiK50与链表中的HONOR70价格相同 输入样例2: 在这里给出一组输入,第四部手机与前面三部的价格都不同。例如: RedmiNote9 1349 HonorX30 1699 VIVOT2X 1599 OPPOk10 2199 输出样例2: 在这里给出相应的输出,第四部手机与前面三部的价格都不同。例如: 排序前,链表中的数据: 型号:RedmiNote9,价格:1349 型号:HonorX30,价格:1699 型号:VIVOT2X,价格:1599 排序后,链表中的数据: 型号:RedmiNote9,价格:1349 型号:VIVOT2X,价格:1599 型号:HonorX30,价格:1699 链表中的对象,没有一个与OPPOk10价格相同的
06-02
以下是Java代码实现: ```java import java.util.*; class MobilePhone implements Comparable<MobilePhone> { private String type; private int price; public MobilePhone(String type, int price) { this.type = type; this.price = price; } public String getType() { return type; } public int getPrice() { return price; } @Override public int compareTo(MobilePhone o) { return this.price - o.price; } @Override public String toString() { return "型号:" + this.type + ",价格:" + this.price; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); List<MobilePhone> list = new LinkedList<>(); // 输入三部手机的信息,创建对象并加入链表 for (int i = 1; i <= 3; i++) { System.out.print("输入第" + i + "部手机的型号、价格:"); String type = scanner.next(); int price = scanner.nextInt(); list.add(new MobilePhone(type, price)); } // 输出排序前的链表信息 System.out.println("排序前,链表中的数据:"); for (MobilePhone mp : list) { System.out.println(mp); } // 对链表进行排序 Collections.sort(list); // 输出排序后的链表信息 System.out.println("排序后,链表中的数据:"); for (MobilePhone mp : list) { System.out.println(mp); } // 查找第四部手机的价格是否与链表中某个对象的价格相同 System.out.print("输入第四部手机的型号、价格:"); String type = scanner.next(); int price = scanner.nextInt(); boolean found = false; for (MobilePhone mp : list) { if (mp.getPrice() == price) { found = true; System.out.println(type + "与链表中的" + mp.getType() + "价格相同"); break; } } if (!found) { System.out.println("链表中的对象,没有一个与" + type + "价格相同的"); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值