Как выбрать рекурсивно в mysql?

у меня две таблицы

components
 id | number | name  | context | ...
-------------------------------------
 1  |  1234  | Test  |   car   | ...
 2  |  1235  | Test  |   car   | ...
 3  |  1236  | Test  |   car   | ...
 4. |  1237  | Test  |   car   | ...
... |   ...  | ...   |   car   | ...
_____________________________________
> 100.000 rows
boms
 id | parent | child | count
----------------------------
 1  |  1234  | 1235  |   1
 2  |  1234  | 1236  |   1
 3  |  1236  | 1237  |   2
... |   ...  | ...   |  ...
____________________________
> 500.000 rows

Цель этой таблицы в том, что components — это список компонентов со всеми подробностями, относящимися к этому компоненту. Таблица boms представляет собой «Список материалов», в котором показано, какой компонент встроен в другой компонент и сколько раз.

Результат в виде дерева:

1234
  |-- 1x 1235
  |-- 1x 1236
           |-- 2x 1237

Есть много компонентов и много бомб, а также много контекстов. Сколько их неизвестно и сколько уровней может иметь спецификация, также неизвестно.

Поскольку я вообще не знаю, как сделать следующее, к сожалению, я не могу предоставить фрагмент кода:

TLTR:

Я хочу указать номер и контекст и получить список компонентов/дочерних элементов все, которые имеет указанный номер в этом контексте. Если контекст не указан, запрос должен дать мне все дочерние элементы, независимо от контекста.

Вот рабочий пример с моими примерными данными: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=9599f911adb48563c789fa4fc513195d

Поскольку я вообще не знаю, как сделать следующее, к сожалению, я не могу предоставить код Не причина. CREATE TABLE для обеих таблиц, INSERT INTO с некоторыми образцами данных (достаточно 5-7 строк) и желаемый вывод для этих данных может быть сделан "руками". Создавайте и предоставляйте.
Akina 17.03.2022 11:08

@Akina Спасибо за ваш отзыв. Я добавил скрипку к моему вопросу.

PeterPan 17.03.2022 11:27

(1) Ваша версия MySQL действительно 5.7? (2) Предоставьте желаемый результат (в виде отформатированной таблицы) для этих данных. (3) Та же самая рабочий пример в другой онлайн-скрипке, которая кажется мне более полезной: dbfiddle.uk/…

Akina 17.03.2022 11:31

Нет, это не так. Спасибо. Я добавил вашу ссылку в свой вопрос

PeterPan 17.03.2022 11:37

Это скрипт, который строит простое представление дерева: dbfiddle.uk/… PS. CHAR(255) может быть слишком коротким — при необходимости расширьте его.

Akina 17.03.2022 11:43

Но это берет «все», а не всех детей заданного числа, с учетом заданного контекста.

PeterPan 17.03.2022 11:48

Просто измените WHERE в якорном подзапросе, например, WHERE `number` = 1234, и вы получите дерево, начинающееся с нужного номера. WHERE EXISTS обеспечивает построение дерева только из корневых узлов.

Akina 17.03.2022 11:51

Использование WHERE number` = 1234 AND NOT EXISTS ...` работает, но WHERE number` = 1236 AND NOT EXISTS ...` не запускается в этом узле

PeterPan 17.03.2022 12:04

Вы должны заменить и удалить условие НЕ СУЩЕСТВУЕТ, а не добавлять еще одно условие.

Akina 17.03.2022 12:05

Да, это работает, но даже без всего AND NOT EXISTS ( SELECT NULL FROM boms WHERE components.number = boms.child) тоже работает

PeterPan 17.03.2022 12:12

Сомневаюсь... dbfiddle.uk/…

Akina 17.03.2022 12:39

Плохо, вы хотите добавить свой запрос в качестве ответа, чтобы я мог принять его в. Было бы более полезно для дальнейшего использования. В любом случае: Большое спасибо. Наконец, это решение!

PeterPan 17.03.2022 14:27
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
13
41
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это скрипт, который строит простое представление дерева:

WITH RECURSIVE
cte AS ( 
    SELECT `number`, CAST(`number` AS CHAR(255)) path
    FROM components
    WHERE NOT EXISTS ( SELECT NULL
                       FROM boms
                       WHERE components.`number` = boms.child )
  UNION ALL
    SELECT boms.child, CONCAT(cte.path, '/', boms.child)
    FROM cte
    JOIN boms ON cte.`number` = boms.parent
)
SELECT `number`, components.name, components.context, boms.count, cte.path
FROM cte
JOIN components USING (`number`)
LEFT JOIN boms ON `number` = boms.child

рабочий пример

Если вам нужно дерево для одного определенного узла, измените WHERE в подзапросе привязки, удалите условие WHERE NOT EXISTS и добавьте условие, которое выбирает нужный начальный узел, например WHERE `number` = 1234.

PS. CHAR(255) может быть слишком коротким — при необходимости расширьте его.

Другие вопросы по теме