Сортировщик алгоритмов SQL - PullRequest
1 голос
/ 04 июля 2019

Это мои данные таблицы. Если cat_parent_id равен 0, это означает, что его родитель, например «Люди и культура», является родителем с cat_id = 1, «Преимущества и сертификация сотрудников» являются потомками людей и культуры. Тем не менее, пособия и сертификации работника также есть ребенок. Вознаграждения работникам cat_id = 6, поэтому его ребенок - SSS Loan Inquiry, в то время как Сертификация имеет cat_id = 10, Свидетельство о трудоустройстве и Свидетельство о взносах SSS будут его ребенком.

enter image description here

Ожидаемый результат:

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

Основная цель - сортировка данных в алфавитном порядке по родителям (первый приоритет), категории (второй приоритет), подкатегории (третий приоритет). Я играю со своим сортировщиком псевдонимов, но не могу заставить его работать.

1 Ответ

1 голос
/ 05 июля 2019

В версиях, предшествующих 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)

A db fiddle для обоих запросов.

...