数据库左右值法计算问题,请大家指点一下

livan1038 2010-07-08 06:46:29
数据库左右值法计算问题,请大家指点一下 :

下面是一个典型的多层数据结构示意图:



相关创建数据语句:
CREATE TABLE category(
category_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
parent INT DEFAULT NULL);


INSERT INTO category
VALUES(1,'ELECTRONICS',NULL),(2,'TELEVISIONS',1),(3,'TUBE',2),
(4,'LCD',2),(5,'PLASMA',2),(6,'PORTABLE ELECTRONICS',1),
(7,'MP3 PLAYERS',6),(8,'FLASH',7),
(9,'CD PLAYERS',6),(10,'2 WAY RADIOS',6);

SELECT * FROM category ORDER BY category_id;

在这种数据结构中,各层之间通过字段 parent 来形成邻接表,我们查询某些层级的关系的时候一般都是通过递归的方式,遍历某个层级关系的SQL的查询次数会顺着层级的增加,想想在层级有20的时候,根据某个底层节点取它到顶层节点的查询次数吧。

为了解决这个问题,人们想出了嵌套集模型(The Nested Set Model),请看下图:



上图依然是表现的与图一相同的层级关系,但是却更换了一种表现形式 下面是新的关系表和数据(关系和数据与之前相同,但是表结构不一样):



CREATE TABLE nested_category (
category_id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
lft INT NOT NULL,
rgt INT NOT NULL
);


INSERT INTO nested_category
VALUES(1,'ELECTRONICS',1,20),(2,'TELEVISIONS',2,9),(3,'TUBE',3,4),
(4,'LCD',5,6),(5,'PLASMA',7,8),(6,'PORTABLE ELECTRONICS',10,19),
(7,'MP3 PLAYERS',11,14),(8,'FLASH',12,13),
(9,'CD PLAYERS',15,16),(10,'2 WAY RADIOS',17,18);


SELECT * FROM nested_category ORDER BY category_id;

这里将 left,right 修改为 lft,rgt因为这两个词在MYSQL中属于关键字 下面我们将插入的数据标识在图上:

同样,我们将数据标识在原来的结构上:




怎么样,是不是很明确了

下面使我自己标定一种形式,方便理解

[1
[2
[3 4]
[5 6]
[7 8]
9]
[10
[11
[12 13]
14]
[15 16]
[17 18]
19]
20]

===========================================================
以上是MySQL 所推荐的左右值法(毗邻目录法、预排序历遍法)

我的想法是根据category的内容,用一个存储过程来计算,把结果算出来放到nested_category中。

请大家指点一下有没有好的方法。
...全文
116 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
javaneteban 2011-11-11
  • 打赏
  • 举报
回复
问下为什么,这个存储过程,我无法运行啊,报错
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS

DECLARE @COUNTER INT
DECLARE @MAX_COUNTER INT
DECLARE @CURRENT_TOP INT
' at line 1
livan1038 2010-07-09
  • 打赏
  • 举报
回复
===========================结贴。
花了一个晚上,终于想出来一个自己觉得好一点的方法,但还是谢谢大家啦,拿出来和大家分享一下:
我多建了一个和category 一样结构的category_temp表。

CREATE PROCEDURE ADJ_NEST AS

DECLARE @COUNTER INT
DECLARE @MAX_COUNTER INT
DECLARE @CURRENT_TOP INT

DELETE FROM CATEGORY_TEMP

INSERT INTO CATEGORY_TEMP
SELECT * FROM CATEGORY

DELETE FROM NESTED_CATEGORY

INSERT INTO NESTED_CATEGORY(NAME,CATEGORY_ID,LFT,RGT)
SELECT 1, CATEGORY_ID, 1, NULL
FROM CATEGORY_TEMP
WHERE PARENT IS NULL

DELETE FROM CATEGORY_TEMP
WHERE PARENT IS NULL

SET @COUNTER = 2
SET @MAX_COUNTER = 2 * (SELECT COUNT(*) FROM CATEGORY_TEMP)+2
SET @CURRENT_TOP = 1

WHILE @COUNTER <= @MAX_COUNTER
BEGIN
IF EXISTS (SELECT *
FROM NESTED_CATEGORY AS S1, CATEGORY_TEMP AS T1
WHERE S1.CATEGORY_ID = T1.PARENT
AND S1.NAME = @CURRENT_TOP)
BEGIN
INSERT INTO NESTED_CATEGORY(NAME,CATEGORY_ID,LFT,RGT)
SELECT (@CURRENT_TOP + 1), MIN(T1.CATEGORY_ID), @COUNTER, NULL
FROM NESTED_CATEGORY AS S1, CATEGORY_TEMP AS T1
WHERE S1.CATEGORY_ID = T1.PARENT
AND S1.NAME = @CURRENT_TOP

DELETE FROM CATEGORY_TEMP
WHERE CATEGORY_ID = (SELECT CATEGORY_ID
FROM NESTED_CATEGORY
WHERE NAME = @CURRENT_TOP + 1)

SET @COUNTER = @COUNTER + 1
SET @CURRENT_TOP = @CURRENT_TOP + 1
END
ELSE
BEGIN
UPDATE NESTED_CATEGORY
SET RGT = @COUNTER,
NAME = -NAME
WHERE NAME = @CURRENT_TOP

SET @COUNTER = @COUNTER + 1
SET @CURRENT_TOP = @CURRENT_TOP - 1
END
END
GO
livan1038 2010-07-09
  • 打赏
  • 举报
回复
高手都潜水了。。。
Mr_Bean 2010-07-09
  • 打赏
  • 举报
回复
什么叫左右值法? 这个结构不就是使用递归SQL实现的么
yangxiao_jiang 2010-07-09
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wwwwa 的回复:]

学习,MYSQL没有递归查询SQL语句,只有用SP了
[/Quote]
db2里带 的,用with就可以。
WWWWA 2010-07-09
  • 打赏
  • 举报
回复
学习,MYSQL没有递归查询SQL语句,只有用SP了
liyan93834183 2010-07-09
  • 打赏
  • 举报
回复
关注,学习一下
ACMAIN_CHM 2010-07-08
  • 打赏
  • 举报
回复
http://blog.csdn.net/ACMAIN_CHM/archive/2009/05/02/4142971.aspx
MySQL中进行树状所有子节点的查询

5,889

社区成员

发帖
与我相关
我的任务
社区描述
IBM DB2 是美国IBM公司开发的一套关系型数据库管理系统,它主要的运行环境为UNIX(包括IBM自家的AIX)、Linux、IBM i(旧称OS/400)、z/OS,以及Windows服务器版本
社区管理员
  • DB2
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧