找到无限升级的用户赞助商 PHP?

Find a user's sponsor going infinite levels up PHP?

假设我有一个 MySQL table,如下所示。从底部开始,我想找到一个有 "Status = 1" 的赞助商。但我想按顺序进行。例如我是"Mike"。我的赞助商是 "Richard"。我想检查 "Richard" 的状态是否为 1。他没有。所以现在我要检查 "Richard" 的赞助商,看看他的状态是否为 1。他也没有。所以我一直往上走,检查我的赞助商的赞助商的赞助商......等等。

通常情况下,如果我想检查多个级别,我可以使用一个或多个查询来做到这一点。但是如果我想检查无限级别直到找到状态为 1 的赞助商,问题就出现了?那是怎么工作的? php query/function 看起来像检查无限级别吗?

    Sponsors     Referrals      Status
    --------------------------------------
    Zack         Joey             1
    Joey         Tracy            0
    Tracy        Helen            0
    Helen        Richard          0
    Richard      Mike             0

根据我的理解,您希望所有状态为 1 的发起人倒序排列

SELECT * FROM `table`
where status = 1
ORDER BY id DESC

试试这个。

在 php 中这样做在我看来是错误的方法,因为它会导致从应用程序到数据库的 N 个请求(其中 N 是必须处理的级别,直到发起人具有所需状态被发现)。有人可能会对此进行优化,但基本问题总是相同的。

数据基本上代表了一个树结构(如果赞助商总是只能推荐一个人,则为列表)。

在关系数据库中有表示树的模式,但它需要更改数据库结构(Nested set is but one example for this). Bill Karwin has a nice slidedeck on the topic

如果您不限于 MySQL 或者可以等到 MySQL 8.0 发布,使用 CTE/Recursive queries 也是一个选择。

任何情况下的好处是,一旦您拥有树结构,您就不会仅限于一个用例。

附录

php 不是我选择的编程语言,因此我不能特别推荐一个库。但是似乎有几个库可供选择:

虽然解决方案似乎确实像 Lawrence 所建议的那样具有 parent_id,但我认为我会给出 PHP 解决方案,假设你已经有了数组中的人员列表(即,不是每对一个查询,因为那真的很浪费)。

您需要做的是递归遍历数组,从赞助商到赞助商,直到找到状态为 1 的赞助商。看看这个函数:

<?php
$people = [
    [
        "sponsor" => "Zack",
        "referal" => "Joey",
        "status" => 1,
    ],
    [
        "sponsor" => "Joey",
        "referal" => "Tracy",
        "status" => 0,
    ],
    [
        "sponsor" => "Tracy",
        "referal" => "Helen",
        "status" => 0,
    ],
    [
        "sponsor" => "Helen",
        "referal" => "Richard",
        "status" => 0,
    ],
    [
        "sponsor" => "Felipe",
        "referal" => "Juan",
        "status" => 0,
    ],
    [
        "sponsor" => "Richard",
        "referal" => "Mike",
        "status" => 0,
    ],
];
static $i = 0;
function getParentSponsor($referal, $people) {
    foreach ($people as $pair) {
        if ($pair["referal"] === $referal) {
            if ($pair["status"] === 1) { // we found our parent sponsor
                return $pair["sponsor"];
            }
            else {
                return getParentSponsor($pair["sponsor"], $people); // we need to go to the next element
            }
            return $pair["sponsor"];
        }
    }
    $i++;
}
echo getParentSponsor("Mike", array_reverse($people)).PHP_EOL; // Zack
echo getParentSponsor("Richard", array_reverse($people)).PHP_EOL; // Zack
echo getParentSponsor("Joey", array_reverse($people)).PHP_EOL; // Zack

Demo