层级查询
Hierarchy Query
我想知道如何才能成功查询我与用户之间的层次结构。我已经发布了一个类似的问题,但结构发生了变化,现在只有执行官才能为他们分配客户。
有这个级别的用户:
- 导演
- 经理
- 行政人员
示例 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。
我想知道如何才能成功查询我与用户之间的层次结构。我已经发布了一个类似的问题,但结构发生了变化,现在只有执行官才能为他们分配客户。
有这个级别的用户:
- 导演
- 经理
- 行政人员
示例 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。