层次结构查询

时间:2017-11-13 18:32:05

标签: mysql sql hierarchical-data

我想知道如何成功查询我与用户的层次结构。我发布了一个类似的问题,但结构发生了变化,现在只有高管可以为他们分配客户。

有这样级别的用户:

  1. 管理器
  2. 执行
  3. 示例表USERS:

    ID    username    privilege   parent_ID
    1     Director1   1           null
    2     Director2   1           null
    3     Manager1    2           1
    4     Manager2    2           1
    5     Manager3    2           2
    6     Executive1  3           3
    7     Executive2  3           3
    8     Executive3  3           4
    9     Executive4  3           4
    10    Executive5  3           5
    11    Executive6  3           5
    

    他们会有他们的“顾客”。

    示例表COSTUMERS

    ID  name  User_ID
    1   c1    11
    2   c2    10
    3   c3    10
    4   c4    9
    5   c5    8
    6   c6    7
    7   c7    6
    

    我的问题在于我应该建立什么样的联接,以便每个用户只能看到他们被允许的客户,规则是他们只能看到他们下面的高管的客户,以及高管们只能看到他们自己的客户。

    Diagram

    例如,在上图中,如果用户要检查他的客户,他应该看到:

    导演1:C7,C6,C5,C4

    导演2:C3,C2,C1

    经理1:C7,C6

    经理2:C5,C4

    Manager3:C3,C2,C1

    高管只会看到自己的客户。

1 个答案:

答案 0 :(得分:2)

解决这个问题的正确方法是使用递归CTE查询,它将在MySQL 8.0中出现:https://dev.mysql.com/doc/refman/8.0/en/with.html

WITH RECURSIVE h AS (
  SELECT ID FROM USERS WHERE ID = ?
  UNION
  SELECT ID FROM USERS AS u JOIN h ON u.parent_ID = h.ID
)
SELECT c.*
FROM h
JOIN COSTUMERS AS c ON c.User_ID = h.ID;

如果您仍在使用MySQL 5.7或更早版本,则需要更加笨拙地进行操作。您有一个优点,即您的层次结构具有固定的最大深度。

SELECT c.*
FROM (
    SELECT e.ID FROM USERS AS e
    WHERE e.ID = ?
    UNION ALL 
    SELECT e.ID FROM USERS AS e 
    JOIN USERS AS m ON e.parent_ID = m.ID
    WHERE m.ID = ?
    UNION ALL 
    SELECT e.ID FROM USERS AS e 
    JOIN USERS AS m ON e.parent_ID = m.ID
    JOIN USERS AS d ON m.parent_ID = d.ID
    WHERE d.ID = ?
) AS h
JOIN COSTUMERS AS c ON c.User_ID = h.ID;

我假设将您的层次结构重组为像Closure Table这样的另一种设计是不可能的。但如果您对其他设计感兴趣,请参阅我对What is the most efficient/elegant way to parse a flat table into a tree?

的回答

或我的演讲https://www.slideshare.net/billkarwin/models-for-hierarchical-data

或我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming