sql >> Base de Datos >  >> RDS >> Mysql

Mysql ordenando datos jerárquicos

He estudiado http://explainextended.com/2009/03 /17/consultas-jerárquicas-en-mysql/ y encontró una solución para su problema. Supongo que ya tiene su solución, pero para cualquier otro que esté buscando la misma solución, respondo aquí.

Mi solución también funcionará para tablas relacionales, ya que no podemos establecer cero (0) en el campo principal en la tabla relacional. Será NULL y mi solución también funciona perfectamente para tablas relacionales.

La Función

DROP FUNCTION IF EXISTS hierarchy_connect_by_parent_eq_prior_id;
DELIMITER $$
CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INTEGER
NOT DETERMINISTIC
READS SQL DATA
BEGIN
    DECLARE _parent INT;
    DECLARE _rank INT;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;

    SET _parent = @id;
    SET _rank = 0;

    IF @id IS NULL THEN
            RETURN NULL;
    END IF;

    LOOP
        SET @innerrank = 0;
        SELECT p.id 
        INTO   @id
        FROM   (
                SELECT   id, @innerrank := @innerrank+1 AS rank 
                FROM     yourTable 
                WHERE    COALESCE(parent, 0) = _parent 
                ORDER BY yourField
                ) p 
        WHERE   p.rank > _rank LIMIT 0, 1;
        IF @id IS NOT NULL OR _parent = @start_with THEN
                SET @level = @level + 1;
                RETURN @id;
        END IF;
        SET @level := @level - 1;
        SET @innerrank = 0;
        SELECT COALESCE(p.parent, 0), p.rank
        INTO   _parent, _rank
        FROM   (
                SELECT id, parent, @innerrank := @innerrank+1 AS rank
                FROM    yourTable
                WHERE   COALESCE(parent, 0) = (
                    SELECT COALESCE(parent, 0) FROM yourTable WHERE id = _parent
                    ) 
                ORDER BY yourField
               ) p
        WHERE p.id = _parent;
    END LOOP;       
END;
$$
DELIMITER ;

Reemplace yourTable con el nombre de su tabla y yourField con su nombre de campo por el que desea ordenar sus datos.

La consulta

SELECT ou.* FROM (
    SELECT hi.id, parent, yourField FROM (
        SELECT hierarchy_connect_by_parent_eq_prior_id(id) AS id, 
            @level AS level 
            FROM (
                SELECT @start_with := 0, @id := @start_with, @level := 0
                 ) vars, yourTable 
            WHERE @id IS NOT NULL
        ) ho 
    JOIN yourTable hi ON hi.id = ho.id
) ou

Reemplace yourTable con el nombre de su tabla y yourField con el nombre de su campo que desea mostrar.

Esto producirá el resultado que usted requiere. Lo probé y funciona bien.

Aquí está http://sqlfiddle.com/#!9/9d060d/2 para verlo en acción.