需要使用MYSQL获取所有推荐ID

时间:2011-01-16 11:03:45

标签: mysql

我有一个如下的推荐表。

> id     referredByID  referrerID
> 
> 1001    1              2
> 
> 1002    2              3
> 
> 1003    2              4
>
> 1004    5              7

从上面的表结构中,我需要获得我推荐的用户以及推荐人推荐的用户。

例如:

  • referByID-1

  • 我提到了 ID - 2

  • 现在 ID - 2 引用 ID -3

  • 在同样的情况下 ID-2 引用 ID - 4

现在我的输出需要看起来像:

推荐由我完成:

id - 2

id - 3

id - 4

如何使用MYSQL完成此任务。

任何帮助将不胜感激..提前致谢...

3 个答案:

答案 0 :(得分:2)

我认为我的一切都是正确的,但是你的命名惯例使我感到困惑,所以你最好检查一切。

如果我调用以下存储过程:

call referrals_hier(1);

我得到以下结果:

+--------------+------------+-------+
| referredByID | referrerID | depth |
+--------------+------------+-------+
|            1 |          2 |     0 |
|            2 |          3 |     1 |
|            2 |          4 |     1 |
+--------------+------------+-------+
3 rows in set (0.00 sec)

完整的脚本:http://pastie.org/1466596

存储过程

drop table if exists referrals;
create table referrals
(
id smallint unsigned not null primary key,
referrerID smallint unsigned not null,
referredByID smallint unsigned null,
key (referredByID)
)
engine = innodb;

insert into referrals (id, referredByID, referrerID) values
 (1001,1,2),(1002,2,3),(1003,2,4),(1004,5,7);

drop procedure if exists referrals_hier;

delimiter #

create procedure referrals_hier
(
in p_refID smallint unsigned
)
begin

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

create temporary table hier(
 referredByID smallint unsigned, 
 referrerID smallint unsigned, 
 depth smallint unsigned
)engine = memory;

insert into hier select referredByID, referrerID, v_dpth from referrals where referredByID = p_refID;

/* 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 referrals e inner join hier on e.referredByID = hier.referrerID and hier.depth = v_dpth) then

        insert into hier select e.referredByID, e.referrerID, v_dpth + 1 
            from referrals e inner join tmp on e.referredByID = tmp.referrerID and tmp.depth = v_dpth;

        set v_dpth = v_dpth + 1;            

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

    else
        set v_done = 1;
    end if;

end while;

select * from hier order by depth;

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

end #

delimiter ;

-- call this sproc from your php

call referrals_hier(1);

希望这会有所帮助:)

答案 1 :(得分:0)

有两种方法,这两种方式都在这里用例子描述:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

答案 2 :(得分:0)

这些是MySQL缺乏对递归公用表表达式的支持的情况。

如果您的级别有上限,那么您可以使用多个自连接执行此操作:

SELECT l1.referredID, l2.referredID, ...
FROM your_table l1
  LEFT JOIN your_table l2 ON l2.referredByID = l1.referredID
  LEFT JOIN your_table l3 ON l3.referredByID = l2.referredID
  LEFT JOIN your_table l4 ON l4.referredByID = l3.referredID
  ... (you get the picture)

现在你可以看到,当有更多关卡时,这会变得很难看,而对于较大的关卡也不会表现得很好。

如果您无法更改表格设计,那么我建议您对可以拥有的最大深度进行一次很好的猜测,并创建一个可以检索所有级别的视图。至少这使得应用程序或ad-hoc查询更容易。

除此之外(巨大的自联接)视图,您还可以构建另一个视图,将每个级别作为自己的行返回。但那会更慢。

但只要您处理MySQL,最好的办法就是更改表设计以使用嵌套集模型,该模型在Anonymous87发布的MySQL手册的链接中有所描述。