【问题标题】:MySQL query counting keys from tree-like structureMySQL 查询计算树状结构中的键
【发布时间】:2015-06-17 22:53:48
【问题描述】:

我有三张桌子:

 Department(ID,name) , 
 SubDepartment(parentID,childID) and 
 Department_Employees(idEmployee, idDepartment)
  1. 在“Department_Employees”表中,idDepartment 是外键链接的 到“部门”表的 ID。
  2. 在“SubDepartment”表中,parentID 和 childID 是外键,都链接到“Department”表的 ID。

一个Department(parent)可以有多个SubDepartments(children),而那些SubDepartments可以有自己的SubDepartments(children) SubDepartment(child) 不能是其任何父部门的父级。 “idEmployee” 在表“Department_Employees”中是不同的(Employee 只能属于一个部门)。这些规则从前端覆盖。

我必须计算某个部门及其所有子部门中有多少员工(“idEmployee”)。我还必须计算某个部门中有多少子部门,包括所有孩子。

假设我有这样的东西:

 1. MainDepartment(6 employees)



 - ITSector(3 employees)

    * Databases(4 employees)
    * Programmers(2 employees)


 - DeliverySector(4 employees)

我需要输出为 MainDepartment 有 4 个子部门和 19 名员工。

是否可以或建议在一个带有子查询的查询中执行此操作?我认为我需要为此进行某种递归,但我不知道如何编写它。

【问题讨论】:

  • 但是部门代码和Iddepartment代码重叠?可能是 iddepartment =1 和 childdepartment =1?
  • 它确实重叠,但这种情况以及循环情况都在前面排序。之所以有三个表而不是仅将部门链接到自身,是因为子部门表中还有字段日期,因为我需要能够跟踪孩子切换父母的历史。
  • 我发布了一个解决方案,您必须在 subdp 表中插入一个列名。他们不能重叠,怎么能分辨出1的儿子谁是他的父亲?您必须更改某些内容,可能将所有内容放在同一个表中,并且 parentid=-1 用于主要部门。如果重叠,下面的查询会给出错误的结果。

标签: mysql database


【解决方案1】:

您可以使用嵌套集模型来存储分层数据。这意味着您的表格将采用以下形式: Department(ID,name, parentID, left, right ) and Department_Employees(idEmployee, idDepartment)

    SELECT COUNT(parent.name), COUNT(employee.id)
FROM Department AS node ,
     Department AS parent,
     Department_employee AS employee
WHERE node.lft BETWEEN parent.lft AND parent.rgt
        AND node.idDepartment = product.idDepartment
        AND parent.name = 'MAIN DEPARTMENT';

More on Nested set representation for hierarchical data

其他选项是保持数据库结构相同。您可以使用sub queriesstored procedure 来查找子部门。

select count(id), count(distinct(idDepartment)) from Department_employee 
                   where idDepartment IN ( Getsubdepartment('Department') );

【讨论】:

    【解决方案2】:

    递归听起来像:

    WITH RECURSIVE dep (main_id,child_id,name) as
    (SELECT d.id,d.id,d.name 
     FROM department d
     UNION ALL
     SELECT d.main_id, sd.child, d.name || '.' || sd.name
     FROM dep d INNER JOIN subdepartment sd on d.child_id=sd.parentid
    )
    SELECT s.name,count(idemployee) 
    FROM dep d INNER JOIN dep s ON d.name LIKE s.name || '%'
    LEFT JOIN department_employees de ON d.child_id=de.iddepartment
    GROUP BY s.name
    ORDER BY s.name;
    

    在 postgres 上测试它应该也可以在 mysql 中工作。

    它使用存储树的路径系统。这是非常好的和容易的。左右不适用于大而动态的树,因为在每个插入时您都必须更新一半数据库。如果您复制粘贴一个分支,您将更新数百万条记录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多