使用perl进行递归查询

发布于 2024-12-18 01:52:31 字数 496 浏览 0 评论 0原文

我在 db 上有下表,其中有 2 列:

from      to    
00001     00002
00001     00003
00002     00003
00002     00004
00003     00001
00003     00004
00002     00004
00004     00002
00005     00003
00005     00001
00006     00007
00009     00006

我需要使用 perl 和 dbi 获取特定编号的连接,例如 00001 的输出将是以下连接:

00001 00002 0003 00004 00005

因为 00001 连接到 00002 和 00003,并且 00002 和 00003 连接到那些新号码 00004 和 00005 。

有没有一种算法可以实现这个算法,perl 中实现这种算法的最佳解决方案是什么?

I have the following table on db which has 2 columns :

from      to    
00001     00002
00001     00003
00002     00003
00002     00004
00003     00001
00003     00004
00002     00004
00004     00002
00005     00003
00005     00001
00006     00007
00009     00006

I need to get with perl and dbi the connection of specific number, for example the output of 00001 will be the below connection :

00001 00002 0003 00004 00005

because 00001 connected to 00002 and 00003 and 00002 and 00003 connected to those new number 00004 and 00005 .

Is there an algorithm to implement this and what is the best solution in perl to implement such algorithm ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

倾城°AllureLove 2024-12-25 01:52:31

看来您想找到一个连接的子树(它是一个有向图,例如一棵树,所以您需要树算法)。

这是使用树搜索算法 - DFS(深度优先搜索)或 BFS(呼吸优先搜索)来完成的。您可以在 SQL 或 Perl 中实现其中之一(或者在 DBI 混合中实现,尽管它比纯 SQL 或纯 Perl 解决方案更烦人)。

一般的 BFS 是:

  • 创建一个队列(提示:在 Perl 中,队列和堆栈自然由数组表示)

  • < p>将原始节点存储到队列中。

  • 当队列不为空时,重复:

    • 将第一个节点 N 从队列中弹出。

    • 将该节点标记为“已遍历”。最简单的方法是将 %seen 哈希中键为 N 的哈希元素设置为值 1。

    • N 打印到路径

    • 从 N 个连接的 DB 中查找所有节点。

    • 将上一步中尚未看到的节点添加到队列末尾。

  • 结束循环。

It seems that you want to find a connected subtree (it's a directed graph, e.g. a tree, so you want tree algos).

This is done using tree search algorithms - DFS (Depth First Search) or BFS (Breath First Search). You can implement either one in SQL or in Perl (or in a DBI mix though it's more annoying than pure SQL or pure Perl solution).

The general BFS would be:

  • Create a queue (Hint: in Perl, queues and stacks are naturally represented by arrays)

  • Store the original node in the queue.

  • While the queue is not empty, repeat:

    • Pop the first node N off the queue.

    • Mark that node as "traversed". The easiest approach is to set a hash element in a %seen hash with a key of N to a value of 1.

    • Print N to the path

    • Find all the nodes from DB connected from N.

    • Add those nodes from the last step that have NOT yet been seen to the end of the queue.

  • End loop.

请别遗忘我 2024-12-25 01:52:31

一种可能的方法:

sub AllReachable {
    my ( $dbi, $sql, @todo ) = @_;
    my %done;
    while (@todo) {
        my $res = $dbi->selectcol_arrayref( sprintf $sql, join( ",", @todo ) );
        @done{@todo} = ();
        @todo = grep {!exists $done{$_}} @$res;
    }
    return keys %done;
}

my @result = AllReachable($dbi, 'SELECT DISTINCT to FROM table WHERE from IN (%s)', 1);

One possible approach:

sub AllReachable {
    my ( $dbi, $sql, @todo ) = @_;
    my %done;
    while (@todo) {
        my $res = $dbi->selectcol_arrayref( sprintf $sql, join( ",", @todo ) );
        @done{@todo} = ();
        @todo = grep {!exists $done{$_}} @$res;
    }
    return keys %done;
}

my @result = AllReachable($dbi, 'SELECT DISTINCT to FROM table WHERE from IN (%s)', 1);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文