php - laravel 递归按级别/深度显示推荐的用户
问题描述
因此,我正在与会员合作,并在注册和保存谁推荐用户方面做得很好,现在我正在努力向这些用户展示按级别推荐的用户。
级别未保存在数据库中,我认为它是在逻辑区域中递增?
用户表结构
id | name | sponsor_id |
1 | John | NULL |
2 | Jane | 1 |
3 | Jess | 1 |
4 | Joe | 2 |
所以我想要的输出应该是这样的:
I am John
,level 1 是谁的sponsor_id 是我的,level 2 谁的sponsor_id 是我邀请的 id。
ID | Name | Level |
2 | Jane | 1 |
3 | Jess | 1 |
4 | Joe | 2 |
其中Jane & Jess
的赞助商 ID 是我的,而Joe
赞助商 ID 是Jess
用户有赞助商
public function sponsor()
{
return $this->belongsTo('App\User', 'sponsor_id');
}
用户有推荐
public function referrals()
{
return $this->hasMany('App\User', 'sponsor_id');
}
解决方案
如果 MySQL 8(非常建议使用像您这样的分层数据),您可以使用递归 CTE 执行此操作:
WITH RECURSIVE CTE_users_levels(id, name, level) AS
(
SELECT id, name, 0 as level
FROM users
WHERE sponsor_id IS NULL
UNION ALL
SELECT u.id, u.name, cte.level+1
FROM CTE_users_levels cte
JOIN users u ON cte.id=u.sponsor_id
)
-- To output all users' levels:
SELECT * FROM CTE_users_levels ORDER BY level;
现在您有了包含所有用户列的虚拟表level
,您可以查询它
| id | name | level |
| --- | ---- | ----- |
| 1 | John | 0 |
| 2 | Jane | 1 |
| 3 | Jess | 1 |
| 4 | Joe | 2 |
进一步...
从您的 CTE 中查看
CREATE VIEW VIEW_User_Levels AS
(
WITH RECURSIVE CTE_users_levels(id, name, level) AS
(
SELECT id, name, 0 as level
FROM users
WHERE sponsor_id IS NULL
UNION ALL
SELECT u.id, u.name, cte.level+1
FROM CTE_users_levels cte
JOIN users u ON cte.id=u.sponsor_id
)
SELECT * FROM CTE_users_levels ORDER BY level
)
现在很容易获得所有用户级别(无需 CTE 声明):
SELECT * FROM VIEW_User_Levels
然后,如果您有很多用户,那么一直重新计算整个树(VIEW 就是这样做的)就有点过时了
然后,您可以在新列中修复用户的级别。
ALTER TABLE users ADD level INT;
并在您的视图的帮助下为所有用户填充该列:
UPDATE users u, VIEW_User_Levels v
SET u.level=v.level
WHERE u.id=v.id;
这使
SELECT * FROM users
id name sponsor_id level
1 John null 0
2 Jane 1 1
3 Jess 1 1
4 Joe 2 2
如果您有很多用户,并且您的目标是大量查询级别列,请索引 IT。
请注意,您也可以仅更新一个用户的级别值(例如,如果其赞助商_id 更改,或者如果用户是新用户)
UPDATE users u, VIEW_User_Levels v
SET u.level=v.level
WHERE u.id=v.id AND u.name='Jane';
推荐阅读
- angularjs - Angular 2 vs AngularJS CSP(内容安全策略)绕过易感性
- xml - 如何在转换 xsllt 期间获取额外的参数
- node.js - 节点 - 无法获取 /api/posts
- google-bigquery - 问:如何从表中排除人名
- visual-studio-code - VScode Search 在远程机器上无法正常工作
- apache-flink - 如果我将自动提交设置为 true 和
- javascript - 在客户端生成可下载的文件流
- notepad++ - Notepad++ 帮助:在节点之后添加属性
- android - notifyDataSetChange() 在适配器中不起作用
- c# - 无法以编程方式删除 PDF 文件