2011-03-11 4 views
0

私はカテゴリのリストを描こうとしています、このようなサブとサブなど。私のカテゴリのテーブルレイアウトを描くMysql複数の結合

 
Root    Sub Level 1 
Personal income Adelaide IT Solutions (AITS) 
Personal income DJ 
Personal income Ebay Sales 
Personal income IAG 
Rental income Cash Grove Pasadena 
Rental income Winston Ave Cumberland Park 
Personal income Misc Income 

私はだけ、私は3つのレベルの深行くに参加している場合加入、例えば、それが唯一持っているのカテゴリの一覧が表示されます、それが一致したときのために、結果を返します。次のSQL文を書きました深いカテゴリ。

私は入れ子の選択を使用しなければならないと思っていますか、それと似たようなものですが、どうやってそれをどうするのか分かりません。

SELECT 
    c.name as 'Root', 
    s.name as 'Sub Level 1', 
    s2.name as 'Sub Level 2', 
    s3.name as 'Sub Level 3' 
FROM catergories c 
    INNER JOIN catergories s ON c.id = s.parent 
    INNER JOIN catergories s2 ON s.id = s2.parent 
    INNER JOIN catergories s3 ON s2.id = s3.parent 

ご協力いただければ幸いです。

+0

が入れ子集合というhttp://dev.mysql.com/tech-resources/articles/hierarchical-data.html –

+0

注意を参照してください...あなたのカテゴリを従業員に置き換えますモデルは検索には最適ですが、更新は隣接リストモデルよりもはるかに多くの作業が必要です。さらに、この記事で紹介した唯一の更新アルゴリズムはノードの追加と削除ですが、時々はサブツリー全体を移動したいこともあります。 –

+0

それは読み込みにはそれほど素晴らしいものではありません。 –

答えて

0

が存在する場合は、最大が深い3つのレベルで、最も簡単な実装はルート列内のすべてのカテゴリを表示するにはLEFT JOINを使用して、そのサブカテゴリにされるだろうと仮定:

SELECT 
c.name as 'Root', 
s.name as 'Sub Level 1', 
s2.name as 'Sub Level 2', 
s3.name as 'Sub Level 3' 
FROM catergories c 
LEFT JOIN catergories s ON c.id = s.parent 
LEFT JOIN catergories s2 ON s.id = s2.parent 
LEFT JOIN catergories s3 ON s2.id = s3.parent 

ます上記のクエリでは持っています多くの重複 - すべてのカテゴリがルートとして表示され、それらのいくつかはさまざまなレベルのサブカテゴリとして再び表示されます。ルートとしてだけ親を持っているために、私はあなたがルールを追加することができますね。

SELECT 
c.name as 'Root', 
s.name as 'Sub Level 1', 
s2.name as 'Sub Level 2', 
s3.name as 'Sub Level 3' 
FROM catergories c 
LEFT JOIN catergories s ON c.id = s.parent 
LEFT JOIN catergories s2 ON s.id = s2.parent 
LEFT JOIN catergories s3 ON s2.id = s3.parent 
WHERE c.parent IS NULL 
-- or parent=-1, or whatever a category with no parent has for in the parent column 
あなたがDBにアプリケーション層からの単一の呼び出しを行い、必要を取得することができます
0

かなり簡単な非再帰的な隣接リストのストアドプロシージャの実装階層。

mysql> call employees_hier(1); 
+--------+-----------------+-------------+-----------------+-------+ 
| emp_id | emp_name  | boss_emp_id | boss_name  | depth | 
+--------+-----------------+-------------+-----------------+-------+ 
|  1 | f00    |  NULL | NULL   |  0 | 
|  2 | ali later  |   1 | f00    |  1 | 
|  3 | megan fox  |   1 | f00    |  1 | 
|  4 | jessica alba |   3 | megan fox  |  2 | 
|  5 | eva longoria |   3 | megan fox  |  2 | 
|  6 | keira knightley |   5 | eva longoria |  3 | 
|  7 | liv tyler  |   6 | keira knightley |  4 | 
|  8 | sophie marceau |   6 | keira knightley |  4 | 
+--------+-----------------+-------------+-----------------+-------+ 
8 rows in set (0.00 sec) 

明らか

drop table if exists employees; 
create table employees 
(
emp_id smallint unsigned not null auto_increment primary key, 
name varchar(255) not null, 
boss_id smallint unsigned null, 
key (boss_id) 
) 
engine = innodb; 

insert into employees (name, boss_id) values 
('f00',null), 
    ('ali later',1), 
    ('megan fox',1), 
     ('jessica alba',3), 
     ('eva longoria',3), 
     ('keira knightley',5), 
      ('liv tyler',6), 
      ('sophie marceau',6); 


drop procedure if exists employees_hier; 

delimiter # 

create procedure employees_hier 
(
in p_emp_id smallint unsigned 
) 
begin 

declare v_done tinyint unsigned default(0); 
declare v_dpth smallint unsigned default(0); 

create temporary table hier(
boss_id smallint unsigned, 
emp_id smallint unsigned, 
depth smallint unsigned 
)engine = memory; 

insert into hier select boss_id, emp_id, v_dpth from employees where emp_id = p_emp_id; 

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

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

while not v_done do 

    if exists(select 1 from employees e inner join hier on e.boss_id = hier.emp_id and hier.depth = v_dpth) then 

     insert into hier select e.boss_id, e.emp_id, v_dpth + 1 
      from employees e inner join emps on e.boss_id = emps.emp_id and emps.depth = v_dpth; 

     set v_dpth = v_dpth + 1;    

     truncate table emps; 
     insert into emps select * from hier where depth = v_dpth; 

    else 
     set v_done = 1; 
    end if; 

end while; 

select 
e.emp_id, 
e.name as emp_name, 
p.emp_id as boss_emp_id, 
p.name as boss_name, 
hier.depth 
from 
hier 
inner join employees e on hier.emp_id = e.emp_id 
left outer join employees p on hier.boss_id = p.emp_id; 

drop temporary table if exists hier; 
drop temporary table if exists emps; 

end # 

delimiter ; 

-- call this sproc from your php 

call employees_hier(1); 
関連する問題