mysql - 层次查询

标签 mysql sql hierarchical-data

我想知道如何成功查询我与用户的层次结构。我曾发布过类似的问题,但结构发生了变化,现在只有高管才能将客户分配给他们。

用户有以下级别:

  1. 董事
  2. 经理
  3. 执行官

示例表用户:

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

经理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;

我假设将您的层次结构重组为另一种设计(例如闭包表)是不可能的。但如果您对其他设计感兴趣,请参阅我对 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 Volume 1: Avoiding the Pitfalls of Database Programming .

关于mysql - 层次查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47271194/

相关文章:

MySql 贷款表,为每个借款人找到根贷款人

从 bash 脚本运行查询时 MySQL 复制不起作用

mysql - MySQL 中的大文本数据类型

MySQL Workbench——第一个连接 "Internal Error"

mysql - 反转使用行排名的 SQL 子查询的顺序

mysql - SQL FOREIGN KEY CONSTRAINT命名差异

c# - 插入失败时防止先前插入

php - 从多个 $_GET 构建 WHERE 子句

c++ - 分层数据模型的替代方案

mysql - 从具有特定根的 SQL 表中获取最新分支的最有效方法是什么?