【问题标题】:Get parent users child user for only level 7th仅获取第 7 级的父用户子用户
【发布时间】:2017-10-31 12:06:09
【问题描述】:

我试图让 Parent 的用户只从 1 级到 7 级。

我还想显示用户数,例如 1 级共有 15 个用户。

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

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

下面是用户表结构:

我怎样才能达到如下截图所示的效果:

请帮帮我。

【问题讨论】:

  • 到目前为止您尝试过哪个查询?
  • @shahsani,我无法为此创建查询。所以这就是我在这里发帖的原因。
  • @mageDev0688 只是一对一吗?
  • @BasheerAhmedKharoti,是的,这只是一对一,但每个用户都有一个子用户,他们只会从 1 级到 7 级。
  • 如果一个用户有多个,那么这怎么可能是一对一的呢?

标签: php mysql


【解决方案1】:

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

简单地说,具有层次结构的节点在“数据模型”中只能有 2 个连接,它们是父节点和子节点。

对于多对多关系,您可以有 6 个相互关联的用户,这将为您提供类似 6^6 or 46,656 的可能组合(或类似的东西,无论如何它的方式超过 2 个)。

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

这些级别不一定会按照您的预期工作(当然我不知道它们是什么),但如果您有一个多对多的关系,那么从逻辑上讲

 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。现在你怎么知道要使用哪个级别?

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

这是我发现的一张图片,显示了这一点,使用学生和班级。这里的想法是一样的,除了我们可以为关系的双方使用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,我们会获得该用户的所有关系。

这似乎更符合你在 cmets 中所说的话,但我仍然不确定我是否完全理解你想要什么。

最后一件非常重要的事情,对于桥牌桌。确保您了解小提琴中用于此的复合主键

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;

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

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 字段添加到我们的数据库架构中。这将是活动的 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;

【讨论】:

  • 在我的情况下,我应该使用哪一个?你能推荐我吗?
  • 如我所说,我会使用物化路径。
  • 现在关于您的问题。你说Parent from 1 to 7th level only,是指直系子女吗?或在其树中具有这些 id 的“节点”。仅以#7 为例,如果你看#9 有#8 作为它的父级,而#8 有#7 作为它的父级,那么#7 将是#l9 的“祖父”。换句话说,#9 将 #7 作为其树的一部分。因此,通过选择 1-7(如果它在树中的任何位置),基本上将包含您的所有数据。
  • 另外,当您说第 7 级时,您实际上是指 level 列,还是指父列。
  • 我认为您对用户级别的看法与我对级别的看法不同。你的看起来是用户的访问级别,而不是他们在树中的级别,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 2021-06-09
  • 2019-04-10
相关资源
最近更新 更多