我有一个如下的推荐表。
> 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完成此任务。
任何帮助将不胜感激..提前致谢...
答案 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手册的链接中有所描述。