1

这是我的表格数据。如果 cat_parent_id 为 0,则表示它是父级,例如 People and Culture 是 cat_id = 1 的父级,Employee Benefits and Certification 是 People and Culture 的子级。但是,员工福利和认证也有孩子。Employee Benefits cat_id = 6,所以他的孩子是SSS Loan Inquiry,而Certification 有一个cat_id = 10,就业证明和SSS 供款证明将是他的孩子。

在此处输入图像描述

预期输出:

Admin and Facilities
  • Safety and Security Related Concerns
     • CCTV Footage

Information Technology
  • User Account
     • Enable / Disable Access

People and Culture
     • Certification
        • Certificate of Employment
        • SSS Certificate of Employment
     • Employee Benefits Request
        • SSS Loan Inquiry

我现在有这样的事情没有运气。

SELECT category.cat_id AS catId, category.cat_parent_id AS catParentId, 
subcategory.cat_id AS subcatId,subcategory.cat_parent_id AS subcatParentId,
category.cat_name,
CONCAT( IFNULL(subcategory.cat_parent_id, category.cat_parent_id), 
category.cat_parent_id, category.cat_id, category.cat_name) AS sorter
FROM ticket_categories AS category
LEFT JOIN ticket_categories AS subcategory ON subcategory.cat_parent_id = 
category.cat_id
GROUP BY category.cat_id
ORDER BY sorter

主要目标是按父级(第一优先级)、类别(第二优先级)、子类别(第三优先级)的字母顺序对数据进行排序。我正在使用我的别名分类器,但我无法让它工作。

4

1 回答 1

1

在 MySQL 8 之前的版本中,递归查询很棘手。在您的情况下,您似乎只有 3 个级别(0、1 和 2),因此最好多次自外连接您的表以获取从根到每个节点的路径。

最后对从根到子的“路径”中名称的串联进行排序:

select a.cat_id, a.cat_level, a.cat_name, 
    concat(
        ifnull(concat(c.cat_name, '  '), ''),
        ifnull(concat(b.cat_name, '  '), ''),
        a.cat_name) as cat_order
from ticket_categories a
left join ticket_categories b on b.cat_id = a.cat_parent_id 
left join ticket_categories c on c.cat_id = b.cat_parent_id 
order by cat_order;

您可以轻松扩展此查询以支持更多级别;只需添加那么多left join行和表别名并concat相应地扩展表达式。

在 MySQL 8 中,您可以使用可以处理任意数量级别的递归查询:

with recursive cte(cat_id, cat_level, cat_name, cat_order) as (
  select cat_id, cat_level, cat_name, cat_name
  from ticket_categories
  where cat_parent_id = 0
  union
  select t.cat_id, t.cat_level, t.cat_name, concat(cte.cat_order, '  ', t.cat_name)  
  from cte
  inner join ticket_categories t on t.cat_parent_id = cte.cat_id
)
select * from cte
order by cat_order;

两个查询的输出:

cat_id | cat_level | cat_name                             | cat_order
-------+-----------+--------------------------------------+-------------------------------------------------------------------------------
   3   |     0     | Admin and Facilities                 | Admin and Facilities
   4   |     1     | Safety and Security Related Concerns | Admin and Facilities  Safety and Security Related Concerns
   9   |     2     | CCTV Footage Request                 | Admin and Facilities  Safety and Security Related Concerns  CCTV Footage Request
   2   |     0     | Information Technology               | Information Technology
   5   |     1     | User Account                         | Information Technology  User Account
   8   |     2     | Enable / Disable Access              | Information Technology  User Account  Enable / Disable Access
   1   |     0     | People and Culture                   | People and Culture
  10   |     1     | Certification                        | People and Culture  Certification
  11   |     2     | Certificate of Employment            | People and Culture  Certification  Certificate of Employment
  12   |     2     | SSS Certificate of Contributions     | People and Culture  Certification  SSS Certificate of Contributions

cat_order路径 ( )中使用双空格作为分隔符。这假设您的姓名中不会有双空格。如果你有,如果你的名字中一个是另一个的前缀,那么这个顺序可能会出错

对于最终的缩进格式,您将使用该cat_level列。但在我看来,这样的任务不属于 SQL,虽然它很容易做到

concat(repeat('  ', cat_level), cat_name)

两个查询的数据库小提琴

于 2019-07-05T09:01:43.827 回答