层级查询

Hierarchy Query

我想知道如何才能成功查询我与用户之间的层次结构。我已经发布了一个类似的问题,但结构发生了变化,现在只有执行官才能为他们分配客户。

有这个级别的用户:

  1. 导演
  2. 经理
  3. 行政人员

示例 table 用户:

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"。

示例table 消费者

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

我的问题是我应该进行什么样的连接,这样每个用户都只能看到他们被允许看到的客户,规则是他们只能看到他们下面的管理人员的客户, 高管将只能看到自己的客户。

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

导演 1:C7、C6、C5、C4

导演 2:C3、C2、C1

经理 1:C7、C6

经理 2:C5、C4

经理 3:C3、C2、C1

而且高管们只会见自己的客户。

解决这个问题的正确方法是使用递归 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