数据库对层次结构的处理模型有好多种,能够依据自己的需求来设计模型。当然最简单的也是最easy设计的模型就是所谓的邻接模型。在这方面,其它数据库比方Oracle 提供了现成的分析方法 connect by,而MySQL在这方面就显得有些薄弱了。 只是能够用MySQL的存储过程实现ORACLE相似的分析功能

这样,先来创建一个简单的数表。

create table country ( id number(2) not null,  name varchar(60) not null);
create table country_relation (id number(2), parentid number(2));

插入一些数据

-- Table country.
insert into country (id,name) values (0,'Earth');
insert into country (id,name) values (2,'North America');
insert into country (id,name) values (3,'South America');
insert into country (id,name) values (4,'Europe');
insert into country (id,name) values (5,'Asia');
insert into country (id,name) values (6,'Africa');
insert into country (id,name) values (7,'Australia');
insert into country (id,name) values (8,'Canada');
insert into country (id,name) values (9,'Central America');
insert into country (id,name) values (10,'Island Nations');
insert into country (id,name) values (11,'United States');
insert into country (id,name) values (12,'Alabama');
insert into country (id,name) values (13,'Alaska');
insert into country (id,name) values (14,'Arizona');
insert into country (id,name) values (15,'Arkansas');
insert into country (id,name) values (16,'California'); -- Table country_relation.
insert into country_relation (id,parentid) values (0,NULL);
insert into country_relation (id,parentid) values (2,0);
insert into country_relation (id,parentid) values (3,0);
insert into country_relation (id,parentid) values (4,0);
insert into country_relation (id,parentid) values (5,0);
insert into country_relation (id,parentid) values (6,0);
insert into country_relation (id,parentid) values (7,0);
insert into country_relation (id,parentid) values (8,2);
insert into country_relation (id,parentid) values (9,2);
insert into country_relation (id,parentid) values (10,2);
insert into country_relation (id,parentid) values (11,2);
insert into country_relation (id,parentid) values (12,11);
insert into country_relation (id,parentid) values (13,11);
insert into country_relation (id,parentid) values (14,11);
insert into country_relation (id,parentid) values (15,11);
insert into country_relation (id,parentid) values (16,11);

在Oracle 里面。对这些操作就比較简单了。都是系统提供的。

比方以下四种情形:
1). 查看深度,

select max(level) "level" from COUNTRY_RELATION a start with a.parentid is NULL
connect by PRIOR a.id = a.PARENTID
order by level; level
----------
4 已用时间: 00: 00: 00.03

2). 查看叶子节点

select name from
(
select b.name, connect_by_isleaf "isleaf"
from COUNTRY_RELATION a inner join country b on (a.id = b.id)
start with a.parentid is NULL connect by prior a.id = a.PARENTID
) T where T."isleaf" = 1; NAME
--------------------------------------------------
Canada
Central America
Island Nations
Alabama
Alaska
Arizona
Arkansas
California
South America
Europe
Asia
Africa
Australia 已选择13行。 已用时间: 00: 00: 00.01

3) 查看ROOT节点

select connect_by_root b.name
from COUNTRY_RELATION a inner join country b on (a.id = b.id)
start with a.parentid is NULL connect by a.id = a.PARENTID CONNECT_BY_ROOTB.NAME
--------------------------------------------------
Earth 已用时间: 00: 00: 00.01

4). 查看路径

select sys_connect_by_path(b.name,'/') "path"
from COUNTRY_RELATION a inner join country b on (a.id = b.id)
start with a.parentid is NULL connect by prior a.id = a.PARENTID
order by level,a.id; path
--------------------------------------------------
/Earth
/Earth/North America
/Earth/South America
/Earth/Europe
/Earth/Asia
/Earth/Africa
/Earth/Australia
/Earth/North America/Canada
/Earth/North America/Central America
/Earth/North America/Island Nations
/Earth/North America/United States
/Earth/North America/United States/Alabama
/Earth/North America/United States/Alaska
/Earth/North America/United States/Arizona
/Earth/North America/United States/Arkansas
/Earth/North America/United States/California 已选择16行。 已用时间: 00: 00: 00.01

接下来我们看看在MySQL 里面怎样实现上面四种情形:
前三种都比較简单。能够非常easy写出SQL。
1)查看深度

mysql> SELECT COUNT(DISTINCT IFNULL(parentid,-1)) AS LEVEL FROM country_relation
;
+-------+
| LEVEL |
+-------+
| 4 |
+-------+
1 row in set (0.00 sec)

2)查看ROOT节点

mysql> SELECT b.`name` AS root_node FROM
-> (
-> SELECT id FROM country_relation WHERE parentid IS NULL
-> ) AS a, country AS b WHERE a.id = b.id;
+-----------+
| root_node |
+-----------+
| Earth |
+-----------+
1 row in set (0.00 sec)

3).  查看叶子节点

mysql> SELECT b.`name` AS leaf_node FROM
-> (
-> SELECT id FROM country_relation WHERE id NOT IN (SELECT IFNULL(parentid,
-1) FROM country_relation)
-> ) AS a, country AS b WHERE a.id = b.id;
+-----------------+
| leaf_node |
+-----------------+
| South America |
| Europe |
| Asia |
| Africa |
| Australia |
| Canada |
| Central America |
| Island Nations |
| Alabama |
| Alaska |
| Arizona |
| Arkansas |
| California |
+-----------------+
13 rows in set (0.00 sec)

4) 查看路径
这一块没有简单的SQL实现。只是能够用MySQL的存储过程来实现相同的功能。
存储过程代码例如以下:

DELIMITER $$

USE `t_girl`$$

DROP PROCEDURE IF EXISTS `sp_show_list`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_show_list`()
BEGIN
-- Created by ytt 2014/11/04.
-- Is equal to oracle's connect by syntax.
-- Body.
DROP TABLE IF EXISTS tmp_country_list;
CREATE TEMPORARY TABLE tmp_country_list (node_level INT UNSIGNED NOT NULL, node_path VARCHAR(1000) NOT NULL);
-- Get the root node.
INSERT INTO tmp_country_list SELECT 1, CONCAT('/',id) FROM country_relation WHERE parentid IS NULL;
-- Loop within all parent node.
cursor1:BEGIN
DECLARE done1 INT DEFAULT 0;
DECLARE i1 INT DEFAULT 1;
DECLARE v_parentid INT DEFAULT -1;
DECLARE v_node_path VARCHAR(1000) DEFAULT '';
DECLARE cr1 CURSOR FOR SELECT parentid FROM country_relation WHERE parentid IS NOT NULL GROUP BY parentid ORDER BY parentid ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1 = 1; OPEN cr1; loop1:LOOP
FETCH cr1 INTO v_parentid;
IF done1 = 1 THEN
LEAVE loop1;
END IF;
SET i1 = i1 + 1; label_path:BEGIN
DECLARE done2 INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2 = 1;
-- Get the upper path.
SELECT node_path FROM tmp_country_list WHERE node_level = i1 - 1 AND LOCATE(v_parentid,node_path) > 0 INTO v_node_path;
-- Escape the outer not found exception.
IF done2 = 1 THEN
SET done2 = 0;
END IF;
INSERT INTO tmp_country_list
SELECT i1,CONCAT(IFNULL(v_node_path,''),'/',id) FROM country_relation WHERE parentid = v_parentid;
END;
END LOOP; CLOSE cr1; END;
-- Update node's id to its real name.
update_name_label:BEGIN
DECLARE cnt INT DEFAULT 0;
DECLARE i2 INT DEFAULT 0;
SELECT MAX(node_level) FROM tmp_country_list INTO cnt;
WHILE i2 < cnt
DO
UPDATE tmp_country_list AS a, country AS b
SET a.node_path = REPLACE(a.node_path,CONCAT('/',b.id),CONCAT('/',b.name))
WHERE LOCATE(CONCAT('/',b.id),a.node_path) > 0;
SET i2 = i2 + 1;
END WHILE;
END; SELECT node_path FROM tmp_country_list;
END$$ DELIMITER ;

调用结果:

mysql> CALL sp_show_list();
+-----------------------------------------------+
| node_path |
+-----------------------------------------------+
| /Earth |
| /Earth/North America |
| /Earth/South America |
| /Earth/Europe |
| /Earth/Asia |
| /Earth/Africa |
| /Earth/Australia |
| /Earth/North America/Canada |
| /Earth/North America/Central America |
| /Earth/North America/Island Nations |
| /Earth/North America/United States |
| /Earth/North America/United States/Alabama |
| /Earth/North America/United States/Alaska |
| /Earth/North America/United States/Arizona |
| /Earth/North America/United States/Arkansas |
| /Earth/North America/United States/California |
+-----------------------------------------------+
16 rows in set (0.04 sec) Query OK, 0 rows affected (0.08 sec)

MySQL 模拟Oracle邻接模型树形处理的更多相关文章

  1. mysql 模拟oracle中的序列

    因业务需要,把oracle 数据据转成mysql,同时oracle中程序本来一直在用 序列, mysql中没有,所以需要在mysql中新建一个表进行模拟, CREATE TABLE `sequence ...

  2. MySQL模拟Oracle序列使用

    https://www.runoob.com/mysql/mysql-using-sequences.html   一篇笔记开始看 注意:创建序列表时一定要有 主键id自增,否则为只读状态不能修改递增 ...

  3. MySQL实现嵌套集合模型

    MySQL实现嵌套集合模型 译文主要是介绍如何用MySQL来存储嵌套集合数据.在其中会增加一些自己的理解,也会删除掉一些自认为无用的废话. 这篇文章主要讲的是嵌套集合模型,所以邻接表不是本文的重点,简 ...

  4. 【软件实施面试】MySQL和Oracle联合查询以及聚合函数面试总结

    软件实施面试系列文章第二弹,MySQL和Oracle联合查询以及聚合函数的面试总结.放眼望去全是MySQL,就不能来点Oracle吗?之前面过不少公司,也做过不少笔试题,现在已经很少做笔试题了.你肚子 ...

  5. 【无私分享:ASP.NET CORE 项目实战(第十二章)】添加对SqlServer、MySql、Oracle的支持

    目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 增加对多数据库的支持,并不是意味着同时对多种数据库操作,当然,后面,我们会尝试同时对多种数据库操作,这可能需要多个上下文,暂且 ...

  6. qlserver、Mysql、Oracle三种数据库的优缺点总结

    这篇文章主要介绍了sqlserver.Mysql.Oracle三种数据库的优缺点总结,需要的朋友可以参考下   一.sqlserver优点:易用性.适合分布式组织的可伸缩性.用于决策支持的数据仓库功能 ...

  7. MySQL模拟Oralce闪回操作

    在前面的文章中我们介绍了MySQL误操作后数据恢复(update,delete忘加where条件),大概操作是通过sed命令把binlog中相关SQL误操作给逆向回来,然后导入SQL文件来恢复错误操作 ...

  8. 使用动态跟踪技术SystemTap监控MySQL、Oracle性能

    [IT168 技术]本文根据吕海波2018年5月11日在[第九届中国数据库技术大会]上的演讲内容整理而成. 讲师介绍: 吕海波,美创科技研究员,ITPUB管理版版主.出版技术书籍<Oracle内 ...

  9. mysql实现oracle序列

    mysql实现oracle序列的方案1.建表,表结构为:drop table if exists sequence; create table sequence ( seq_name VARCHAR( ...

随机推荐

  1. EXT2/EXT3文件系统(一)

    整理自<鸟哥的Linux私房菜>,整理者:华科小涛http://www.cnblogs.com/hust-ghtao/ 1.文件系统概念引入 文件系统是一种存储和组织计算机数据的方法,它使 ...

  2. Logistic Regression(逻辑回归)(一)基本原理

    (整理自AndrewNG的课件,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 虽然叫做“回归”,但是这个算法是用来解决分类问题的.回归与分类的区 ...

  3. Eclipse TestNg插件

    TestNg作为一个测试框架,也有eclipse的插件: 官网给的安装插件地址是 : For Eclipse 3.4 and above, enter http://beust.com/eclipse ...

  4. Datatable.Compute小技巧

    在个人版机房重构的过程中,大家最发愁的一件事无非就是上下机,结账和报表.那么在结账的过程中,最发愁的是否就数计算日结账单的数据和周结账的数据.还记得在第一遍机房收费系统的过程中用的是for 循环,但是 ...

  5. vc 按钮自绘

    按钮自绘,将按钮区域分成三部分,左边.右边.中间都由贴图绘制,可用于手动进度条按钮,或者左右选择项按钮 cpp代码部分: // LRSkinButton.cpp : implementation fi ...

  6. Mac OS X将CSV格式转换为Excel文档格式,Excel转CSV中文乱码问题

    一:在Mac上假设你使用Excel打开windows导出的CSV格式文档.你会发现表格中全部的的内容都显示在A列. 那么,怎样恢复正常呢,你能够将CSV格式的文档导入到Excel文档中,这样就正常显示 ...

  7. QT 多线程程序设计(也有不少例子)

    QT通过三种形式提供了对线程的支持.它们分别是,一.平台无关的线程类,二.线程安全的事件投递,三.跨线程的信号-槽连接.这使得开发轻巧的多线程Qt程序更为容易,并能充分利用多处理器机器的优势.多线程编 ...

  8. EXTJS4两个ComboBox的数据源联动,解决遇到第二个ComboBox第二次以后显示忙的状态问题

    定义如下[红色部分是后加上的,它是解决问题的关键]: var bu_store = Ext.create('Ext.data.Store', { fields: ['key', 'value'], r ...

  9. 深刻:截获windows的消息并分析实例(DefWindowProc),以WM_NCHITTEST举例(Windows下每一个鼠标消息都是由 WM_NCHITTEST 消息产生的,这个消息的参数包含了鼠标位置的信息)

    1,回调函数工作机制 回调函数由操作系统自动调用,回调函数的返回值当然也是返回给操作系统了. 2,截获操作系统发出的消息,截获到后,将另外一个消息返回给操作系统,已达到欺骗操作系统的目的. 下面还是以 ...

  10. POJ 3040 Allowance 贪心

    这题目的贪心思路还是有一点细节问题的. 还没有证明,据说是因为题目给的条件是每个价格是比它小的价格的倍数才能这么贪心的. 思路如下: 假设要给奶牛的钱为C 1)从大面值到小面值一次拿钱,能拿多少拿多少 ...