找到无限升级的用户赞助商 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
假设我有一个 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