Рекурсивна самодіяльність приєднується


15

У мене є commentsтаблиця, яку можна спростити до цього:

comments
=======
id
user_id
text
parent_id

де parent_idє нульовим, але може бути ключовим для коментаря батьків.


Тепер, як я можу selectвсі нащадки конкретного коментаря?
Коментарі можуть бути на кілька рівнів нижче ...

Відповіді:


16

Ієрархічні запити , як відомі ці рекурсивні запити, не підтримуються для MySQL.

Однак вони підтримуються серед Oracle, Microsoft SQL Server, DB2 та PostgreSQL.

Якщо вам потрібно вирішити, ви можете знайти динамічний (і, таким чином, потенційно небезпечний) трюк тут: /programming/8104187/mysql-hierarchical-queries

Ви також можете знайти обговорення питання про те , щоб зберігати ієрархічні дані з іншими моделями , ніж з списком суміжності (тобто батьківського стовпця) тут: /programming/192220/what-is-the-most-efficient- елегантний шлях до розбору-плоскої таблиці-в-дерево /

Удачі!


Цікаво, як таке рішення у вашому другому посиланні може бути небезпечним. Чи можете ви пояснити це? Інакше ласкаво просимо на сайт!
dezso

3
@dezso: Виправте власник запиту, Quassnoi " * Це не є безпечним для оновлення *, оскільки MySQL чітко не визначає поведінку змінної сесії. Однак це єдиний спосіб вчасно звертатися зі списками суміжності до запиту ." Небезпечним могло бути занадто сильне слово ( потенційно нестабільне ?), Але я вважаю за краще помилятися з боку обережності (плюс, я більше обізнаний в Oracle, ніж MySQL, тому хотів бути надзвичайно обережним). Дякуємо за привітання, до речі! Я давно прихований до мережі SE, і я вирішив, що пора трохи відплатити.
Valmoer

2
Синтаксис WITH [RECURSIVE] тепер підтримується з mysql 8.0. dev.mysql.com/doc/refman/8.0/en/with.html
ClearCrescendo

6

Цей дизайн таблиці є антипаттерном SQL "Наївні дерева", як описав Білл Карвін (дивлячись зі слайда 48 у своїй презентації SQL Antipatterns Strike Back ). Проблема з цією конструкцією конкретно полягає у труднощах з отриманням усіх нащадків (або батьків) вузла. Оскільки ви використовуєте MySQL, ви не можете використовувати загальні вирази таблиць (оператор WITH та його RECURSIVE модифікатор), присутні в інших RDBMS.

Що вам залишається:

  • використовувати альтернативну реалізацію ієрархічної структури даних (відповіді на це питання можуть бути хорошим посиланням на це)
  • будувати запити самооб’єднання з обмеженням глибини. Для глибини = 5 ви можете використовувати щось у рядках:

    SELECT *
    FROM comments AS c1
      JOIN comments AS c2 ON (c2.parent_id = c1.id)
      JOIN comments AS c3 ON (c3.parent_id = c2.id)
      JOIN comments AS c4 ON (c4.parent_id = c3.id)
      JOIN comments AS c5 ON (c5.parent_id = c4.id)
  • використовувати RDBMS, який підтримує функцію RECURSIVE (хоча це, швидше за все, не є варіантом для більшості людей)


2
Я не згоден з Біллом Карвіном тут. Модель суміжності не є антидією. З сучасними СУБД, які підтримують рекурсивні запити (Oracle підтримує це вже понад 20 років), така модель є дуже ефективною для отримання та оновлення.
a_horse_with_no_name

5

MySQL не підтримує рекурсивні запити, такі як потрібний вам.

Те, що я робив деякий час назад, - це писати «Збережені процедури», які забезпечують модель для цього.

Замість того, щоб винаходити колесо, я дам вам посилання на мої минулі публікації з цього приводу:

Коротше кажучи, збережені мною процедури, які я зробив, роблять попередній обхід дерева за допомогою обробки черги

  • GetParentIDByID
  • GetAncestry
  • GetFamilyTree

Батько для всіх дітей (наприклад, процедура зберігання GetFamilyTree)

  • КРОК01) Почніть з parent_idчерги
  • КРОК02) Відмініть наступний parent_idяк поточний
  • STEP03) Введіть усі idзначення, які мають струмparent_id
  • КРОК04) Друкуйте або збирайте коментар
  • КРОК05) Якщо черга не порожня, перейдіть STEP02
  • КРОК06) Ви закінчили !!!

Дитина для всіх батьків (як процедура зберігання GetAncestry)

  • КРОК01) Почніть з idчерги
  • КРОК02) Відмініть наступний idяк поточний
  • STEP03) Задайте parent_idзначення струмуid
  • КРОК04) Друкуйте або збирайте коментар
  • КРОК05) Якщо черга не порожня, перейдіть STEP02
  • КРОК06) Ви закінчили !!!

Перегляньте Збережені процедури в інших моїх публікаціях, щоб побачити реалізацію.

Спробувати !!!


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.