Auto recursivo se une


15

Tengo una commentstabla, que se puede simplificar a esto:

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

donde parent_ides anulable, pero podría ser una clave para su comentario principal.


Ahora, ¿cómo puedo selecttodos los descendientes de un comentario específico?
Los comentarios pueden estar varios niveles abajo ...

Respuestas:


16

Las consultas jerárquicas , como se conocen esas consultas recursivas, no son compatibles con MySQL.

Sin embargo, son compatibles con Oracle, Microsoft SQL Server, DB2 y PostgreSQL, entre otros.

Si necesita una solución alternativa, puede encontrar un truco dinámico (y, por lo tanto, potencialmente peligroso) aquí: /programming/8104187/mysql-hierarchical-queries

También puede encontrar una discusión sobre cómo almacenar datos jerárquicos con otros modelos que no sean una Lista de adyacencia (es decir, la columna Principal ) aquí: /programming/192220/what-is-the-most-efficient- elegante-manera-de-analizar-una-mesa-plana-en-un-árbol /

¡Buena suerte!


Me pregunto cómo esa solución en su segundo enlace puede ser peligrosa. ¿Podrías explicarlo? De lo contrario, ¡bienvenido al sitio!
dezso

3
@dezso: Quassnoi dice el creador de la consulta " * " No es seguro para la actualización * porque MySQL no define claramente el comportamiento de la variable de sesión. Sin embargo, es la única forma de lidiar con las listas de adyacencia de manera oportuna en la consulta ". Peligroso podría haber sido una palabra demasiado fuerte (¿ potencialmente inestable ?), Pero prefiero equivocarme por precaución (además, tengo más conocimientos en Oracle que MySQL, por lo que quería ser más precavido). Gracias por la bienvenida, por cierto! He estado al acecho durante mucho tiempo en la red SE, y decidí que era hora de pagar un poco.
Valmoer

2
La sintaxis WITH [RECURSIVE] ahora es compatible con mysql 8.0. dev.mysql.com/doc/refman/8.0/en/with.html
ClearCrescendo

6

Este diseño de tabla es un "árbol ingenuo" antipatrón de SQL como lo describe Bill Karwin (mirando desde la diapositiva 48 en su presentación SQL Antipatterns Strike Back ). El problema con este diseño específicamente es la dificultad de obtener todos los descendientes (o padres) de un nodo. Como está utilizando MySQL, no puede usar expresiones de tabla comunes (la instrucción WITH y su modificador RECURSIVE) presente en otros RDBMS.

Lo que te queda es:

  • usar una implementación alternativa de estructura de datos jerárquica (las respuestas a esta pregunta pueden ser una buena referencia al respecto)
  • Construir consultas de autounión con un límite de profundidad. Para profundidad = 5 podría usar algo en las líneas de:

    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)
  • use un RDBMS que admita WITH RECURSIVE (aunque esto probablemente no sea una opción para la mayoría de las personas)


2
No estoy de acuerdo con Bill Karwin aquí. El modelo de adyacencia no es un antipatrón. Con un DBMS moderno que admite consultas recursivas (Oracle lo ha respaldado durante más de 20 años), este modelo es muy eficiente para recuperar y actualizar.
a_horse_with_no_name

5

MySQL no admite consultas recursivas como la que necesita.

Lo que hice hace un tiempo fue escribir Procedimientos almacenados que proporcionan el modelo para hacerlo.

En lugar de reinventar la rueda, te daré los enlaces a mis publicaciones anteriores sobre esto:

En resumen, los Procedimientos almacenados que realicé preordenan el recorrido del árbol mediante procesamiento de cola

  • GetParentIDByID
  • GetAncestry
  • GetFamilyTree

Padres de todos los niños (como Procedimiento almacenado GetFamilyTree)

  • PASO01) Comience con un parent_iden una cola
  • PASO 02) Elimina el siguiente parent_idcomo el actual
  • PASO03) Poner en cola todos los idvalores que tienen la corrienteparent_id
  • PASO04) Imprime o recoge el comentario
  • PASO 05) Si la cola no está vacía, vaya a STEP02
  • PASO 06) ¡Has terminado!

Hijo a todos los padres (como Procedimiento almacenado GetAncestry)

  • PASO01) Comience con un iden una cola
  • PASO 02) Elimina el siguiente idcomo el actual
  • PASO03) Poner en cola el parent_idvalor de la corrienteid
  • PASO04) Imprime o recoge el comentario
  • PASO 05) Si la cola no está vacía, vaya a STEP02
  • PASO 06) ¡Has terminado!

Consulte los procedimientos almacenados en mis otras publicaciones para ver la implementación.

Darle una oportunidad !!!


2
SELECT  group_concat(@id :=
        (
        SELECT  id
        FROM    comments
        WHERE   parent_id = @id
        )) AS comment
FROM    (
        SELECT  @id := 1
        ) vars
STRAIGHT_JOIN
        comments
WHERE   @id IS NOT NULL

violín

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.