ホームページ データベース mysql チュートリアル 【原创】MySQL模拟Oracle邻接模型树形处理

【原创】MySQL模拟Oracle邻接模型树形处理

Jun 07, 2016 pm 02:53 PM
mysql oracle オリジナル 対処する モデル シミュレーション

数据库对层次结构的处理模型有好多种,可以根据自己的需求来设计模型,当然最简单的也是最容易设计的模型就是所谓的邻接模型。在这方面,其他数据库比如Oracle 提供了现成的分析方法 connect by,而MySQL在这方面就显得有些薄弱了。 不过可以用MySQL的存储过

数据库对层次结构的处理模型有好多种,可以根据自己的需求来设计模型,当然最简单的也是最容易设计的模型就是所谓的邻接模型。在这方面,其他数据库比如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 里面如何实现上面四种情形:

前三种都比较简单,可以很容易写出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)
mysql>
ログイン後にコピー


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>
ログイン後にコピー


このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

MySQL:世界で最も人気のあるデータベースの紹介 MySQL:世界で最も人気のあるデータベースの紹介 Apr 12, 2025 am 12:18 AM

MySQLはオープンソースのリレーショナルデータベース管理システムであり、主にデータを迅速かつ確実に保存および取得するために使用されます。その実用的な原則には、クライアントリクエスト、クエリ解像度、クエリの実行、返品結果が含まれます。使用法の例には、テーブルの作成、データの挿入とクエリ、および参加操作などの高度な機能が含まれます。一般的なエラーには、SQL構文、データ型、およびアクセス許可、および最適化の提案には、インデックスの使用、最適化されたクエリ、およびテーブルの分割が含まれます。

なぜMySQLを使用するのですか?利点と利点 なぜMySQLを使用するのですか?利点と利点 Apr 12, 2025 am 12:17 AM

MySQLは、そのパフォーマンス、信頼性、使いやすさ、コミュニティサポートに選択されています。 1.MYSQLは、複数のデータ型と高度なクエリ操作をサポートし、効率的なデータストレージおよび検索機能を提供します。 2.クライアントサーバーアーキテクチャと複数のストレージエンジンを採用して、トランザクションとクエリの最適化をサポートします。 3.使いやすく、さまざまなオペレーティングシステムとプログラミング言語をサポートしています。 4.強力なコミュニティサポートを提供し、豊富なリソースとソリューションを提供します。

MySQLの場所:データベースとプログラミング MySQLの場所:データベースとプログラミング Apr 13, 2025 am 12:18 AM

データベースとプログラミングにおけるMySQLの位置は非常に重要です。これは、さまざまなアプリケーションシナリオで広く使用されているオープンソースのリレーショナルデータベース管理システムです。 1)MySQLは、効率的なデータストレージ、組織、および検索機能を提供し、Web、モバイル、およびエンタープライズレベルのシステムをサポートします。 2)クライアントサーバーアーキテクチャを使用し、複数のストレージエンジンとインデックスの最適化をサポートします。 3)基本的な使用には、テーブルの作成とデータの挿入が含まれ、高度な使用法にはマルチテーブル結合と複雑なクエリが含まれます。 4)SQL構文エラーやパフォーマンスの問題などのよくある質問は、説明コマンドとスロークエリログを介してデバッグできます。 5)パフォーマンス最適化方法には、インデックスの合理的な使用、最適化されたクエリ、およびキャッシュの使用が含まれます。ベストプラクティスには、トランザクションと準備された星の使用が含まれます

Oracle Loopでカーソルを作成する方法 Oracle Loopでカーソルを作成する方法 Apr 12, 2025 am 06:18 AM

Oracleでは、forループループは動的にカーソルを作成できます。手順は次のとおりです。1。カーソルタイプを定義します。 2。ループを作成します。 3.カーソルを動的に作成します。 4。カーソルを実行します。 5。カーソルを閉じます。例:カーソルをサイクルごとに作成して、上位10人の従業員の名前と給与を表示できます。

Oracle Dynamic SQLを作成する方法 Oracle Dynamic SQLを作成する方法 Apr 12, 2025 am 06:06 AM

SQLステートメントは、Oracleの動的SQLを使用して、ランタイム入力に基づいて作成および実行できます。手順には、次のものが含まれます。動的に生成されたSQLステートメントを保存するための空の文字列変数を準備します。 executeを即座に使用するか、ステートメントを準備して、動的なSQLステートメントをコンパイルおよび実行します。バインド変数を使用して、ユーザー入力またはその他の動的値を動的SQLに渡します。実行するか、実行するか、動的SQLステートメントを実行します。

Apacheのデータベースに接続する方法 Apacheのデータベースに接続する方法 Apr 13, 2025 pm 01:03 PM

Apacheはデータベースに接続するには、次の手順が必要です。データベースドライバーをインストールします。 web.xmlファイルを構成して、接続プールを作成します。 JDBCデータソースを作成し、接続設定を指定します。 JDBC APIを使用して、接続の取得、ステートメントの作成、バインディングパラメーター、クエリまたは更新の実行、結果の処理など、Javaコードのデータベースにアクセスします。

オラクルにトリガーの使用方法 オラクルにトリガーの使用方法 Apr 11, 2025 pm 11:57 PM

Oracleのトリガーは、特定のイベント(挿入、更新、または削除)後に操作を自動的に実行するために使用されるストアドプロシージャです。これらは、データ検証、監査、データメンテナンスなど、さまざまなシナリオで使用されています。トリガーを作成するときは、トリガー名、アソシエーションテーブル、トリガーイベント、トリガー時間を指定する必要があります。トリガーには2種類のタイプがあります。操作前にトリガーが起動され、後のトリガーが操作後に起動されます。たとえば、挿入前のトリガーは、挿入された行の年齢列が負でないことを保証します。

Oracleデータベースを停止する方法 Oracleデータベースを停止する方法 Apr 12, 2025 am 06:12 AM

Oracleデータベースを停止するには、次の手順を実行します。1。データベースに接続します。 2。すぐにシャットダウンします。 3.シャットダウンは完全に中止します。

See all articles