你能在PHP / MySQL的递归函数中使用JOIN吗?

时间:2010-10-12 09:21:13

标签: php mysql recursive-query

我有下表。

CREATE TABLE IF NOT EXISTS `omc_schedule` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `trainer_id` int(11) NOT NULL,
  `course` varchar(255) NOT NULL,
  `capacity` int(11) NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT '1',
  `parentid` int(10) NOT NULL,
  `order` int(11) NOT NULL,
  `booked` int(5) NOT NULL,
  `type` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ...

我可以使用以下函数生成数组树。

 function generateTree(&$tree, $parentid = 0) {
    $this->db->select('*');
    $this->db->where ('parentid',$parentid);
$this->db->where ('active','1');
    $this->db->order_by('order asc, parentid asc');
     $res = $this->db->get('omc_schedule');
     if ($res->num_rows() > 0) {
        foreach ($res->result_array() as $r) {
    // push found result onto existing tree
            $tree[$r['id']] = $r;
            // create placeholder for children
            $tree[$r['id']]['children'] = array();
            // find any children of currently found child
            $this->generateTree($tree[$r['id']]['children'],$r['id']);
         }     
     }
      $res->free_result();
      return $tree;
 }

现在我想加入培训师桌来获得培训师的名字。

CREATE TABLE IF NOT EXISTS `omc_trainer` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `trainer_name` varchar(50) NOT NULL,
  `trainer_image` varchar(100) NOT NULL,
  `video_url` text NOT NULL,
  `desc` text NOT NULL,
  PRIMARY KEY (`id`)
)

现在我尝试以不同的方式加入,但我无法在每个阵列中获得教练的名字。

有什么方法可以使用JOIN在递归函数中获取教练的名字?

上面的函数是CodeIgniter,但请忽略它。

提前致谢。

1 个答案:

答案 0 :(得分:2)

我更喜欢对数据库进行一次调用并返回树/子树,因为它更有效并保持应用程序代码清洁。

以下是您可以查看您感兴趣的示例:

完整的脚本:http://paste.pocoo.org/show/274386/

-- TABLES

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

drop table if exists schedule;
create table schedule
(
sched_id smallint unsigned not null auto_increment primary key,
trainer_id smallint unsigned null,
name varchar(255) not null,
parent_sched_id smallint unsigned null,
key schedule_parent_idx(parent_sched_id),
key schedule_trainer_idx(trainer_id)
)
engine=innodb;


-- STORED PROCEDURES

drop procedure if exists schedule_hier;

delimiter #

create procedure schedule_hier
(
in p_sched_id smallint unsigned
)
begin

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

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

insert into hier select parent_sched_id, sched_id, v_depth from schedule where sched_id = p_sched_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 schedule p inner join hier on p.parent_sched_id = hier.sched_id and hier.depth = v_depth) then

        insert into hier 
            select p.parent_sched_id, p.sched_id,   v_depth + 1 from schedule p 
            inner join tmp on p.parent_sched_id = tmp.sched_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 
 s.sched_id,
 s.name as schedule_name,
 p.sched_id as parent_sched_id,
 p.name as parent_schedule_name,
 t.trainer_id,
 t.name as trainer_name,
 hier.depth
from 
 hier
inner join schedule s on hier.sched_id = s.sched_id
inner join schedule p on hier.parent_sched_id = p.sched_id
inner join trainer t on s.trainer_id = t.trainer_id
order by
 hier.depth, hier.sched_id;

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

end #

delimiter ;

-- TEST DATA

insert into trainer (name) values ('trainer 1'),('trainer 2'),('trainer 3');

insert into schedule (name, trainer_id, parent_sched_id) values
('Schedules',null, null), 
   ('Schedule 1',3,1), 
   ('Schedule 2',2,1), 
      ('Schedule 2-1',1,3), 
      ('Schedule 2-2',3,3), 
        ('Schedule 2-2-1',3,5), 
        ('Schedule 2-2-2',2,5), 
           ('Schedule 2-2-2-1',1,7);

-- TESTING

-- just call this stored procedure from your php

call schedule_hier(3);

sched_id    schedule_name   parent_sched_id parent_schedule_name    trainer_id  trainer_name    depth
========    =============   =============== ====================    ==========  ============    =====
3           Schedule 2          1         Schedules                2              trainer 2    0
4           Schedule 2-1        3         Schedule 2               1              trainer 1    1
5           Schedule 2-2        3         Schedule 2               3              trainer 3    1
6           Schedule 2-2-1      5         Schedule 2-2             3              trainer 3    2
7           Schedule 2-2-2      5         Schedule 2-2             2              trainer 2    2
8           Schedule 2-2-2-1    7         Schedule 2-2-2           1              trainer 1    3