Как получить все продукты, связанные с цепочкой тегов?

У меня есть две таблицы:

// tags
+----+-----------------------+-----------+
| id |         name          | parent_id |
+----+-----------------------+-----------+
| 1  | Home                  | Null      |
| 2  | Kitchen               | 1         |
| 3  | Serving and reception | 2         |
| 4  | Spoon                 | 3         |
| 5  | Digital               | NULL      |
| 6  | Communication         | 5         |
| 7  | Cellphone             | 6         |
+----+-----------------------+-----------+

// products
+----+------------------------------------------+--------+
| id |                name                      | tag_id | -- this is the deepest tag id
+----+------------------------------------------+--------+
| 1  | Dinner Spoon Set,16 Pcs 7.3" Tablespoons | 4      | 
| 2  | iPhone 14 Promax                         | 7      |
| 3  | Samsung A20                              | 7      |
+----+------------------------------------------+--------+

Мне нужно реализовать страницу со списком продуктов для каждого «тега». Итак, мне нужно получить

| 2  | iPhone 14 Promax                         | 7      |
| 3  | Samsung A20                              | 7      |

передав каждый из следующих tag.ids: 5, 6, 7 (поскольку все они относятся к этим продуктам)

Есть идеи, как я могу это сделать?

Упрощенная рабочий пример с реальными данными


Вот мой текущий запрос: (проблема в том, что он возвращает только один продукт, а не список продуктов)

WITH RECURSIVE cte (id, name, parent_id, orig_id) AS (
    SELECT id, name, parent_id, id AS orig_id
    FROM tags
    WHERE parent_id IS NULL
    UNION ALL
    SELECT t1.id, t1.name, t1.parent_id, t2.orig_id
    FROM tags t1
    INNER JOIN cte t2
        ON t2.id = t1.parent_id
)

SELECT MAX(p.name) AS name
FROM cte t
LEFT JOIN products p
    ON p.tag_id = t.id
GROUP BY t.orig_id
HAVING SUM(t.id = 6) > 0;

Каков ожидаемый ввод/вывод данных в скрипте?

Dogbert 18.08.2024 20:45

@Dogbert Ожидаемый результат — это список продуктов, связанных с переданным идентификатором тега. Теги представляют собой иерархию, поэтому, если у продукта tag_id = 10 и у этого тега есть родительский элемент, то продукт все равно необходимо выбрать, если переданный тег идентификатор является родителем

Martin AJ 18.08.2024 20:51

в вашем cte начните с выбора тега, для которого предназначен ваш запрос, а затем рекурсивно найдите его дочерние элементы. поэтому, если вы начинаете с тега 5, ваш cte дает 7, 6 и 5. затем просто выполните простое объединение продуктов с тегом cte.

ysth 18.08.2024 21:06
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
3
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

См. пример

идентификатор имя описание родительский_ид статус создано_at обновлено_at 1 Дом нулевой нулевой активный 2024-08-18 21:33:36 2024-08-18 21:33:36 2 Кухня нулевой 1 активный 2024-08-18 21:33:36 2024-08-18 21:33:36 3 Обслуживание и прием нулевой 2 активный 2024-08-18 21:33:36 2024-08-18 21:33:36 4 Ложка нулевой 3 активный 2024-08-18 21:33:36 2024-08-18 21:33:36 5 Цифровой нулевой нулевой активный 2024-08-18 21:33:36 2024-08-18 21:33:36 6 Коммуникация нулевой 5 активный 2024-08-18 21:33:36 2024-08-18 21:33:36 7 Сотовый телефон нулевой 6 активный 2024-08-18 21:33:36 2024-08-18 21:33:36
идентификатор имя tag_id 1 Набор столовых ложек, 16 столовых ложек диаметром 7,3 дюйма. 4 2 айфон 14 промакс 7 3 Самсунг А20 7
WITH RECURSIVE cte (id, name, parent_id, orig_id) AS (
    SELECT id, name, parent_id, id AS orig_id
    FROM tags
    WHERE id=7 -- start tag
    UNION ALL
    SELECT t1.id, t1.name, t1.parent_id, t2.orig_id
    FROM tags t1
    INNER JOIN cte t2
        ON t2.id = t1.parent_id
)
SELECT p.*,t.*
FROM cte t
inner JOIN products p
    ON p.tag_id = t.id
идентификатор имя tag_id идентификатор имя родительский_ид orig_id 2 айфон 14 промакс 7 7 Сотовый телефон 6 7 3 Самсунг А20 7 7 Сотовый телефон 6 7

рабочий пример
ИЛИ с вашими данными
рабочий пример
Вывод рекурсивного запроса (3 уровня) перед (внутренним) соединением с продуктом

идентификатор имя tag_id идентификатор имя родительский_ид orig_id нулевой нулевой нулевой 10 Мобильные телефоны и аксессуары 2 10 24 Редми Примечание 13 4G 47 47 мобильный телефон 10 10 14 Мобильный телефон Редми А3 47 47 мобильный телефон 10 10 13 Редми Примечание 13 Про 4G 47 47 мобильный телефон 10 10 12 Мобильный телефон Редми 12 47 47 мобильный телефон 10 10 11 Мобильный телефон Samsung Galaxy S24 ультра 47 47 мобильный телефон 10 10 10 Apple iPhone 13 CH 47 47 мобильный телефон 10 10 9 Мобильный телефон Самсунг Галакси А15 47 47 мобильный телефон 10 10 8 Мобильный телефон Редми 13C 47 47 мобильный телефон 10 10 7 Сяоми Поко Х6 Про 5G 47 47 мобильный телефон 10 10 6 Мобильный телефон Самсунг Галакси А55 47 47 мобильный телефон 10 10 5 Мобильный телефон Xiaomi Poco C65 47 47 мобильный телефон 10 10 4 Мобильный телефон Samsung Galaxy S23 Fe 47 47 мобильный телефон 10 10 3 Мобильный телефон Самсунг А05 47 47 мобильный телефон 10 10 1 Мобильный телефон Самсунг А35. 47 47 мобильный телефон 10 10 нулевой нулевой нулевой 48 мобильные аксессуары 10 10 нулевой нулевой нулевой 49 подвижные части 10 10

Однако ваши тестовые данные не включают строки продуктов на промежуточных уровнях иерархии. Попробуйте ввести такие данные для проверки.

В вашей части запроса нет необходимости

GROUP BY t.orig_id
HAVING SUM(t.id = 6) > 0;

Достаточно

WHERE id=6 -- start tag

на якоре.

Судя по моему комментарию выше, я подозреваю, что на самом деле у них нет промежуточных уровней, поэтому рекурсия действительно не нужна. Хотя это позволяет добавить несколько уровней позже.

Barmar 18.08.2024 23:57

Про количество уровней ничего сказать не могу. В приведенных данных их как минимум 3 (db-fiddle.com/f/p7BRJDSYB3wSA36Yg1TNyS/0 ) или ( dbfiddle.uk/ZD1cUNkp).

ValNik 19.08.2024 00:01

Ах да. У них просто нет продуктов на промежуточном уровне, только на листьях.

Barmar 19.08.2024 00:03

Да, это. Я думаю, однако, что промежуточные уровни также должны быть проверены ОП.

ValNik 19.08.2024 00:06

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