仅为第7级获取父用户子用户

时间:2017-10-13 05:39:39

标签: php mysql

我正在尝试仅将父级用户从1级提升到7级。

另外,我想显示1个级别的用户数量总共有15个用户。

我已经厌倦了下面的递归功能,但是它不能正常工作。

PHP How do I calculate level of nested calls in recursive function?

以下是用户表结构:

enter image description here

如何获得如下截图的结果:

enter image description here

请帮帮我们。

1 个答案:

答案 0 :(得分:0)

好的,让我们再试一次。如果它是多对多关系,则不是树或分层数据。

简而言之,具有分层结构的节点在“数据模型”中只能有2个连接。这些连接将是父节点和子节点。

对于多对多的关系,你可以拥有6个彼此相关的用户,这会给你类似6^6 or 46,656种可能的组合(或类似的东西,无论如何它的方式超过2)。< / p>

你提到一些关于关卡的事情,我仍然不知道这是什么。是这个权限级别吗?

这些等级不一定按你的预期工作(当然我不知道它们是什么)但只是逻辑上如果你有多对多关系那么

 If user A is related to User B
 Than
 user B is equally related to User A

假设用户A的级别为1,而用户B的级别为2。现在因为A=B然后B=A。现在你怎么知道使用哪个级别?

无论如何,多对多关系就像数据库架构101,它是基本的。你需要的是一个bridge表(有时称为junction表)。所以你有一个users表,那么你有一个users_users表。

enter image description here

这是我发现的图像,使用学生和班级来展示这一点。它的想法与此相同,只是我们可以将users表用于关系的两个方面。将它们命名为table1_table2是很常见的,因此我们得到users_users。这是一个很好的形象,并展示了我想要的东西,只想到多对多的多对一和多对多的关系(因为它就是这样)。这有助于解释为什么我们需要额外的表而不能在一个表中表示这一点。

在我继续进行更多

之前,先检查一下这个小提琴

https://www.db-fiddle.com/f/6yRBW4jpBJR3MkVpUZP47f/2

这可以通过这种方式显示(以基本方式)

users
    id  :   name
    1   :   A
    2   :   B
    3   :   C
    4   :   D
    5   :   E
    6   :   F
    7   :   G
    8   :   H
    9   :   I

users_users ( brige table )
parent  : child
    1   :   2
    1   :   3
    1   :   4
    1   :   5

    2   :   3
    2   :   4
    2   :   5   

因此,用户1是2,3,4,5的父级,而用户2是3,4,5的父级。重要的是要注意用户可以是父母和另一个用户的孩子。例如:

users_users ( brige table )
parent  : child
    1   :   2
    2   :   1

现在12的父级,21的父级,反之亦然。这意味着你如何编码它以及你想要强加于它的约定。

密切关注小提琴中的选择查询。注意父母的哪一方以及孩子的哪一方。

现在我们可以轻松添加另一个名为level的列。请参阅此小提琴https://www.db-fiddle.com/f/6yRBW4jpBJR3MkVpUZP47f/4

我们更新的架构

users
    id  :   name    :   level
    1   :   A       :       1
    2   :   B       :       2
    3   :   C       :       3
    4   :   D       :       4
    5   :   E       :       5
    6   :   F       :       6
    7   :   G       :       7
    8   :   H       :       8
    9   :   I       :       9

因此,如果我们想要查找给定级别的用户,我们必须决定使用哪个级别。这是因为父和子都是用户,然后都有一个分配给他们的级别。

我想我们应该使用父母级别。因此,如果我们想要找到具有一级父级的所有用户,我们将使用此查询。

    SELECT
        c.id AS child_id, c.name AS child_name, p.level AS parent_level
    FROM
        users AS p
    JOIN
        users_users AS u ON p.id = u.parent
    JOIN
        users AS c ON c.id = u.child
    WHERE
        p.level = 1;

这将返回用户2,3,4,5,它们都是用户1的子级(级别1)。但是,每个用户自己的级别与1不同。如果我们只想要具有级别1的用户。我们只需查询users

 SELECT * FROM users WHERE level=1

我们也可以反过来找到所有有特定水平孩子的父母。为此,我们只需更改我们正在查找的列为父级p.的前缀,然后我们也在WHERE子句中翻转条件以使用子c.,如下所示:

SELECT
    p.id AS parent_id, p.name AS parent_name, c.level AS child_level
FROM
    users AS p
JOIN
    users_users AS u ON p.id = u.parent
JOIN
    users AS c ON c.id = u.child
WHERE
    c.level = 2;

这里我将级别切换为2(没有结果为1),这将返回User1,这对于子级别2,3,4 and 5将会返回1为止。因为我们有这种关系

users_users ( brige table )
parent     : child
1  {lv 1}  :   2  {lv 2}
1  {lv 1}  :   3  {lv 3}
1  {lv 1}  :   4  {lv 4}
1  {lv 1}  :   5  {lv 5}

因此,您可以看到我们是否查找child.level=2我们获得了第一个关系,如果我们执行相反的parent.level=1,我们就会获得该用户的所有关系。

这似乎更适合你在评论中所说的内容,但我仍然不确定我是否完全理解你想要的内容。

对于桥牌表来说,最后一件非常重要的事情。确保你理解了小提琴中使用的复合主键

CREATE TABLE `users_users` (
 `parent` int(10) unsigned NOT NULL,
 `child` int(10) unsigned NOT NULL,
 PRIMARY KEY (`parent`,`child`) #this is the compound key
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这里我们将来自双方parent/child的用户ID组合为主键。这可以防止关系具有重复条目。所以想象一下

的关键
users_users ( brige table )
parent  : child   : {key}
    1   :   2     : {1~2}
    1   :   3     : {1~3}

    2    :  1     : {2~1}  #<-- this is not a duplicate of {1~2}

    #1  :   2     : {1~2}  #<-- this key would be a duplicate
                           # and is not allowed, trying to add this
                           # will throw a duplicate key error from the DB

我几乎忘记了您的status字段,我们可以将其作为简单的boolean字段添加到我们的数据库架构中。对于Active,这将是1,对于非活动,这将是0。

CREATE TABLE `users` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(30) NOT NULL,
    `level` int(10) unsigned NOT NULL,
    `status` tinyint(1) NOT NULL DEFAULT '1',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

然后我们在需要时将它添加到WHERE子句中,非常简单,你可以对它进行排序我确定。 WHERE p.status=1 AND c.level = 2;