Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

MySQL में पदानुक्रमित डेटा से गहराई आधारित पेड़ उत्पन्न करना (कोई सीटीई नहीं)

यदि आप एक संग्रहीत कार्यविधि का उपयोग करते हैं, तो आप इसे php से mysql पर एक ही कॉल में कर सकते हैं:

उदाहरण कॉल

mysql> call category_hier(1);

+--------+---------------+---------------+----------------------+-------+
| cat_id | category_name | parent_cat_id | parent_category_name | depth |
+--------+---------------+---------------+----------------------+-------+
|      1 | Location      |          NULL | NULL                 |     0 |
|      3 | USA           |             1 | Location             |     1 |
|      4 | Illinois      |             3 | USA                  |     2 |
|      5 | Chicago       |             3 | USA                  |     2 |
+--------+---------------+---------------+----------------------+-------+
4 rows in set (0.00 sec)


$sql = sprintf("call category_hier(%d)", $id);

आशा है कि यह मदद करता है :)

पूरी स्क्रिप्ट

टेस्ट टेबल स्ट्रक्चर:

drop table if exists categories;
create table categories
(
cat_id smallint unsigned not null auto_increment primary key,
name varchar(255) not null,
parent_cat_id smallint unsigned null,
key (parent_cat_id)
)
engine = innodb;

टेस्ट डेटा:

insert into categories (name, parent_cat_id) values
('Location',null),
   ('USA',1), 
      ('Illinois',2), 
      ('Chicago',2),  
('Color',null), 
   ('Black',3), 
   ('Red',3);

प्रक्रिया:

drop procedure if exists category_hier;

delimiter #

create procedure category_hier
(
in p_cat_id smallint unsigned
)
begin

declare v_done tinyint unsigned default 0;
declare v_depth smallint unsigned default 0;

create temporary table hier(
 parent_cat_id smallint unsigned, 
 cat_id smallint unsigned, 
 depth smallint unsigned default 0
)engine = memory;

insert into hier select parent_cat_id, cat_id, v_depth from categories where cat_id = p_cat_id;

/* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */

create temporary table tmp engine=memory select * from hier;

while not v_done do

    if exists( select 1 from categories p inner join hier on p.parent_cat_id = hier.cat_id and hier.depth = v_depth) then

        insert into hier 
            select p.parent_cat_id, p.cat_id, v_depth + 1 from categories p 
            inner join tmp on p.parent_cat_id = tmp.cat_id and tmp.depth = v_depth;

        set v_depth = v_depth + 1;          

        truncate table tmp;
        insert into tmp select * from hier where depth = v_depth;

    else
        set v_done = 1;
    end if;

end while;

select 
 p.cat_id,
 p.name as category_name,
 b.cat_id as parent_cat_id,
 b.name as parent_category_name,
 hier.depth
from 
 hier
inner join categories p on hier.cat_id = p.cat_id
left outer join categories b on hier.parent_cat_id = b.cat_id
order by
 hier.depth, hier.cat_id;

drop temporary table if exists hier;
drop temporary table if exists tmp;

end #

टेस्ट रन:

delimiter ;

call category_hier(1);

call category_hier(2);

याहू जियोप्लैनेट प्लेसेस डेटा का उपयोग करते हुए कुछ प्रदर्शन परीक्षण

drop table if exists geoplanet_places;
create table geoplanet_places
(
woe_id int unsigned not null,
iso_code  varchar(3) not null,
name varchar(255) not null,
lang varchar(8) not null,
place_type varchar(32) not null,
parent_woe_id int unsigned not null,
primary key (woe_id),
key (parent_woe_id)
)
engine=innodb;

mysql> select count(*) from geoplanet_places;
+----------+
| count(*) |
+----------+
|  5653967 |
+----------+

ताकि तालिका में 5.6 मिलियन पंक्तियाँ (स्थान) हों, आइए देखें कि php से कॉल की गई आसन्न सूची कार्यान्वयन/संग्रहीत प्रक्रिया कैसे संभालती है।

     1 records fetched with max depth 0 in 0.001921 secs
   250 records fetched with max depth 1 in 0.004883 secs
   515 records fetched with max depth 1 in 0.006552 secs
   822 records fetched with max depth 1 in 0.009568 secs
   918 records fetched with max depth 1 in 0.009689 secs
  1346 records fetched with max depth 1 in 0.040453 secs
  5901 records fetched with max depth 2 in 0.219246 secs
  6817 records fetched with max depth 1 in 0.152841 secs
  8621 records fetched with max depth 3 in 0.096665 secs
 18098 records fetched with max depth 3 in 0.580223 secs
238007 records fetched with max depth 4 in 2.003213 secs

कुल मिलाकर मैं उन ठंडे रनटाइम से बहुत खुश हूं क्योंकि मैं अपने सामने के अंत में डेटा की हजारों पंक्तियों को वापस करने पर विचार करना शुरू नहीं करूँगा बल्कि पेड़ को गतिशील रूप से प्रति कॉल केवल कई स्तरों को लाने के लिए तैयार करूंगा। ओह और अगर आप सोच रहे थे कि innodb myisam की तुलना में धीमा है - मैंने जिस myisam कार्यान्वयन का परीक्षण किया वह सभी मामलों में दोगुना धीमा था।

अधिक सामग्री यहां :http://pastie.org/1672733

आशा है कि यह मदद करता है :)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. त्रुटि:तालिका '<तालिका-नाम>' के लिए उपयोगकर्ता '<userid>'@'<ip-address>' को कमांड अस्वीकृत का चयन करें

  2. EEE MMM dd HH:mm:ss ZZZ yyyy दिनांक स्वरूप java.sql.Date को

  3. MySQL ASIN () फ़ंक्शन - किसी संख्या का आर्क साइन लौटाएं

  4. नेस्टेड क्लासेस - CustomRowMapper !! अब कोई समस्या नहीं !! - भाग ---- पहला

  5. डेटाबेस सेटअप करें और AWS Redshift और Mysql में केवल-पढ़ने के लिए उपयोगकर्ता बनाएं