sql - MySQL 递归查询

标签 sql mysql database optimization recursion

我的数据库架构如下所示:

Table t1:
    id
    valA
    valB

Table t2:
    id
    valA
    valB

我想要做的是,对于其中一个表中的给定行集,查找两个表中具有相同 valA 或 valB 的行(将 valA 与 valA 和 valB 进行比较valB,而不是 valA 和 valB)。 然后,我想查找与上一个查询结果中的行具有相同 valA 或 valB 的行,依此类推

Example data:

t1 (id, valA, valB):
    1, a, B
    2, b, J
    3, d, E
    4, d, B
    5, c, G
    6, h, J

t2 (id, valA, valB):
    1, b, E
    2, d, H
    3, g, B


Example 1:

Input: Row 1 in t1
Output: 
    t1/4, t2/3
    t1/3, t2/2
    t2/1
    ...


Example 2:

Input: Row 6 in t1
Output:
    t1/2
    t2/1

我想要在结果中找到该行的搜索级别(例如,在示例 1 中:t1/2 和 t2 的级别 1)/1,t1/5 的级别 2,...)有限深度的递归没问题。随着时间的推移,我可能想在查询中包含更多遵循相同模式的表。如果可以轻松地为此目的扩展查询,那就太好了。

但最重要的是性能。你能告诉我最快的方法来完成这个任务吗?

提前致谢!

最佳答案

尝试一下,虽然它还没有完全测试,但看起来它正在工作:P(http://pastie.org/1140339)

drop table if exists t1;
create table t1
(
id int unsigned not null auto_increment primary key,
valA char(1) not null,
valB char(1) not null
)
engine=innodb;

drop table if exists t2;
create table t2
(
id int unsigned not null auto_increment primary key,
valA char(1) not null,
valB char(1) not null
)
engine=innodb;

drop view if exists t12;
create view t12 as
select 1 as tid, id, valA, valB from t1
union
select 2 as tid, id, valA, valB from t2;

insert into t1 (valA, valB) values 
('a','B'),
('b','J'),
('d','E'),
('d','B'),
('c','G'),
('h','J');

insert into t2 (valA, valB) values 
('b','E'),
('d','H'),
('g','B');

drop procedure if exists find_children;

delimiter #

create procedure find_children
(
in p_tid tinyint unsigned,
in p_id int unsigned 
)
proc_main:begin

declare done tinyint unsigned default 0;
declare dpth smallint unsigned default 0;


create temporary table children(
 tid tinyint unsigned not null,
 id int unsigned not null,
 valA char(1) not null,
 valB char(1) not null,
 depth smallint unsigned default 0,
 primary key (tid, id, valA, valB)
)engine = memory;

insert into children select p_tid, t.id, t.valA, t.valB, dpth from t12 t where t.tid = p_tid and t.id = p_id; 

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

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

while done <> 1 do

    if exists(
    select 1 from t12 t 
      inner join tmp on tmp.valA = t.valA or tmp.valB = t.valB and tmp.depth = dpth) then

        insert ignore into children
        select 
        t.tid, t.id, t.valA, t.valB, dpth+1 
      from t12 t
      inner join tmp on tmp.valA = t.valA or tmp.valB = t.valB and tmp.depth = dpth;

        set dpth = dpth + 1;            

        truncate table tmp;
        insert into tmp select * from children where depth = dpth;

    else
        set done = 1;
    end if;

end while;

select * from children order by depth;

drop temporary table if exists children;
drop temporary table if exists tmp;

end proc_main #


delimiter ;


call find_children(1,1);

call find_children(1,6);

关于sql - MySQL 递归查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18871873/

相关文章:

mysql - 将时间输入和超时合并在一行mysql中

mysql - 选择其他表不包含同类记录的查询

javascript - select 返回零行,尽管它应该返回一些条目

mysql - 带条件的多个表的SQL查询

MySQL if 条件则左连接

php - 在 PHP 中使用数据库创建类别

java - 在 Hibernate 中使用 saveOrUpdate() 创建新记录而不是更新现有记录

sql - 围绕已知聚类中心的聚类点

php - MYSQL 触发器错误,

java - 如何将连接标记为从 Tomcat 6 中的池中逐出