@符号 - 用于在MySQL递归SELECT查询的解决方案?(@ Symbol - a soluti

2019-09-03 02:27发布

有很多关于在MySQL递归SELECT查询的问题,但大多数的回答是,“有在Mysql的递归SELECT查询无解”。

其实是有一定的解决方案和我想清楚的知道,所以这个问题是对前一个问题是可以被发现的以下( 如何做-DO的递归选查询功能于MySQL的 )

假设你有这个表:

col1 - col2 - col3
1    -  a   -  5
5    -  d   -  3
3    -  k   -  7
6    -  o   -  2
2    -  0   -  8

&你要查找所有在COL1连接到值“1”的链接,即要打印出来:

1 - a - 5
5 - d - 3
3 - k - 7

然后你可以使用这个简单的查询:

select col1, col2, @pv:=col3 as 'col3' from table1
join
(select @pv:=1)tmp
where col1=@pv

好的,好的,但是,如果你的表中有2条记录COL1包含“1”和2条记录中含有COL1“3”,例如:

col1 - col2 - col3
1    -  a   -  5
1    -  m   -  9
5    -  d   -  3
3    -  k   -  7
6    -  o   -  2
3    -  v   -  10
2    -  0   -  8

然后,当用户搜索“1” COL1,它应该显示所有环节连接2“1”,即它应该显示这个期望的结果:

col1 - col2 - col3
1    -  a   -  5
1    -  m   -  9
5    -  d   -  3
3    -  k   -  7
3    -  v   -  10

所以,我的问题是我们如何修改上面的查询,以便它会显示所有环节如上述预期的结果?

编辑:@戈登,但如果我们忽略select distinct col1, col2 from那么这个查询意味着什么,你可以在这方面的工作(因为childID的得到了提高,所以我们可以订购表1):

select col1, col2,
         @pv:=(case when find_in_set(col3, @pv) then @pv else concat(@pv, ',', col3) 
               end) as 'col3'
  from (select * from table1 order by col1) tb1 join
      (select @pv:='1') tmp
      on find_in_set(col1, @pv) > 0

在这种情况下,我们不担心顺序,例如,如果是这样的数据:

col1 - col2 - col3
4    -  a   -  5
1    -  d   -  2
1    -  k   -  4
2    -  o   -  3
6    -  k   -  8
8    -  o   -  9

输出将是:

col1 - col2 - col3
1    -  d   -  1,2
1    -  k   -  1,2,4
2    -  o   -  1,2,4,3

因此,我们得到这样的结果1,2,4,3吧? &我们只是选择的所有记录,如果COL1是1,2,4,3 。 然后我们就可以得到最终的预期结果。

如果是这样的话,你可以认为,排除了我刚才提到的解决方案的任何特殊情况?

Answer 1:

我一直在想,如果像这样的工作:

select distinct col1, col2
from (select col1, col2,
             @pv:=(case when find_in_set(col3, @pv) then @pv else concat(@pv, ',', col3) 
                   end) as 'col3'
      from table1 join
          (select @pv:='1') tmp
          on find_in_set(col1, @pv) > 0
     ) t

像这样的东西应该适用于小数据集。 然而,把所有的ID字符串中的想法是限制在一个字符串的能力。



Answer 2:

有更多的发挥。 不能让它使用用户变量,由于项目的排序工作。

但是,如果你有水平的一个合理的最大数,那么你可以做这样的事情: -

SELECT CONCAT_WS('-', a.allCols, b.allCols, c.allCols, d.allCols, e.allCols, f.allCols, g.allCols, h.allCols, i.allCols, j.allCols, k.allCols, l.allCols, m.allCols)
FROM (SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) a
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) b ON a.col3 = b.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) c ON b.col3 = c.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) d ON c.col3 = d.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) e ON d.col3 = e.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) f ON e.col3 = f.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) g ON f.col3 = g.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) h ON g.col3 = h.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) i ON h.col3 = i.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) j ON i.col3 = j.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) k ON j.col3 = k.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) l ON k.col3 = l.col1
LEFT OUTER JOIN(SELECT col1, col3, CONCAT(col1, col2, col3) AS allCols FROM table1) m ON l.col3 = m.col1
WHERE a.col1 = 1

这是多达13个级别(正常,只在您的测试数据用一对夫妇)的应对,并会给出一个逗号分隔位的每一列,每一行用破折号连接( - )。



Answer 3:

在我有限的层次,水平的深,我用了以下内容:

父母:

select * from mytable
join (
    select A.id Aid,B.id Bid, C.id Cid, D.id Did, E.id Eid, F.id Fid,G.id Gid, H.id Hid from mytable A
    left join mytable B on B.id=A.parent
    left join mytable C on C.id=B.parent
    left join mytable D on D.id=C.parent
    left join mytable E on E.id=D.parent
    left join mytable F on F.id=E.parent
    left join mytable G on G.id=F.parent
    left join mytable H on H.id=G.parent
    where A.id=9
) X
where id in (Aid,Bid,Cid,Did,Eid,Fid,Gid,Hid);

儿童:

select * from mytable where id in (
select distinct id from mytable
join (
    select A.id Aid,B.id Bid, C.id Cid, D.id Did, E.id Eid, F.id Fid,G.id Gid, H.id Hid FROM mytable A
    left join mytable B on B.parent=A.id
    left join mytable C on C.parent=B.id
    left join mytable D on D.parent=C.id
    left join mytable E on E.parent=D.id
    left join mytable F on F.parent=E.id
    left join mytable G on G.parent=F.id
    left join mytable H on H.parent=G.id
    Where A.id=1
) X
where id in (Aid,Bid,Cid,Did,Eid,Fid,Gid,Hid)

);



Answer 4:

存储过程做到这一点的最好办法。 因为如果数据遵循同样的顺序戈登的解决方案只会工作。

如果我们有这样的表结构

col1 - col2 - col3
3 - k - 7
5 - d - 3
1 - a - 5
6 - o - 2
2 - 0 - 8

它不会工作。

下面是一个示例程序代码来实现相同的。

delimiter //
CREATE PROCEDURE chainReaction 
(
    in inputNo int
) 
BEGIN 
    declare final_id int default NULL;
    SELECT col3 into final_id from table1
    where col1 = inputNo;
    if( final_id is not null) then
        insert into results(select col1, col2, col3 from table1 where col1 = inputNo);
        CALL chainReaction(final_id);   
    end if;
END//
delimiter ;

call chainReaction(1);
select * from results;
drop table if exists results;


文章来源: @ Symbol - a solution for Recursive SELECT query in Mysql?