2012-07-12 27 views
6

Estoy trabajando en la gestión de categorías. Donde tengo parentId con cada fila. Las categorías pueden ser n-level. Puedo llamar recursivamente a la función php que devolverá la matriz de árbol de categorías.Consulta de Mysql que devuelve el árbol de categorías

enter image description here

Ahora Problema es: En el panel de administración que quiero categoría página del anuncio, como se muestra a continuación. es decir, qué categoría es bajo qué.

  • Inicio
  • los productos (Editar) (Esconder)
  • Productos> Producto 1 (Editar) (Esconder)
  • Productos> Producto 2 (Editar) (Esconder)
  • Productos> Producto 2 > Producto 2 1 (Editar) (Esconder)
  • Productos>> Producto 2 Producto 2 2 (Editar) (Esconder)
  • Contacto (Editar) (Esconder)

Deseo el resultado de la consulta de MySQL en el mismo orden que se muestra arriba. No estoy seguro de cómo puedo lograrlo.

SELECT * 
FROM tbl_categories 
ORDER BY ??? 

Por favor guía.

+0

mejor uso para el servidor que pgoramming idiomas. – Oyeme

+0

Está trabajando con la programación. Puede haber paginación en el listado, quiero usar el límite con esa consulta. En alguna parte en el carro de compras opensource que he visto, pero no recuerdo cómo lo han hecho. – VibhaJ

+0

por favor muéstrenos la estructura de la tabla, es decir, digamos, quiero 2 obtener la fila Producto 2.1 –

Respuesta

0

No puede lograr esto en una sola consulta de mysql. Bueno, puede lograr esto, al ejecutar múltiples consultas. El algoritmo es el siguiente: Inicialmente cree un objeto de conjunto de datos que rellenará, obteniendo datos de la base de datos. Cree un método que tome el id principal como parámetro y devuelva sus nodos secundarios si está presente, y devuelve -1, si no tiene un elemento secundario. Paso 1: Obtener todas las filas, que no tiene un nodo primario (raíz). Paso 2: Revise este resultado. Por ejemplo, si prod1 y prod2 son los nodos devueltos iniciales, en el conjunto de resultados. Al iterar este RS obtenemos prod1, e insertamos una fila en nuestro obj DataSET. A continuación, enviamos el id de prod1 al método getCHILD, para obtener su hijo, y luego repetimos el resultado devuelto, y llamamos de nuevo al método getCHILD, hasta que no obtengamos el nodo más bajo.

2

No hay consulta SQL simple que puede traerle los resultados ordenados de la manera que espera según esta estructura de tabla.

Hay dos formas de resolver el problema:

  1. usar la lógica aplicación externa (fuera de DB) para hacer llamadas recursivas que descubrirán los niños de cada categoría y construir el árbol en la aplicación.

  2. Utilice uno de los algoritmos para almacenar datos de árbol en una base de datos relacional. Uno de esos algoritmos se llama Modified Preorder Tree Traversal o simplemente MPTT.

Asumiendo que utilizan columnas lft y rgt para mantener índices izquierda/derecha en el recorrido, cuando se inserta una nueva categoría tendrá que:

  1. Get categoría padre información por Id: SELECT lft,rgt FROM tbl_categories WHERE categoryId=5 Supongamos, por ejemplo, que la categoría principal tenía lft=7 y rgt=10 (en este caso ya tiene un hijo)

  2. M Ake espacio para una nueva entrada - cambiar todos los registros por 2 (1 para la LFT y 1 para RGT):

    UPDATE tbl_categories SET rgt=rgt+2 WHERE rgt>=10 ORDER BY rgt DESC

    UPDATE tbl_categories SET lft=lft+2 WHERE lft>=10 ORDER BY lft DESC

Nota aquí ORDER descendente. Como se supone que lft y rgt son únicos, se recomienda establecer una restricción UNIQUE y, a continuación, se debe realizar un orden descendente de actualización para evitar errores de clave duplicados.

  1. Conjunto lft=<former parent rgt> y rgt=<former parent rgt +1> e insertar un nuevo registro ...

    INSERT INTO tbl_categories SET categoryName="New Child",parentCategoryId=5,lft=11,rgt=12,...

Puede encontrar más ejemplos detallados con código si la búsqueda de MPTT PHP MySQL. Hay bastantes tutoriales sobre este tema.

+0

gracias ... comprobándolo .. – VibhaJ

+3

@VibhaJ: otra opción sería una tabla de cierre: http://karwin.blogspot.de/2010/03/rendering-trees-with-closure-tables.html que tiene el beneficio añadido que puede tener claves foráneas para garantizar que la categoría padre realmente exista. –

+0

Por cierto, suelo usar MPTT mientras mantengo el padre (e incluso agrego profundidad) en la tabla, entonces no tiene la trampa de encontrar parientes inmediatos ... – poncha

2

puede usar una función almacenada que buscará recursivamente la ruta raíz y concatenará con su elemento primario.

DELIMITER $$ 
DROP FUNCTION IF EXISTS `get_category`$$ 
CREATE FUNCTION `get_category`(cat_id int) RETURNS VARCHAR(255) 
READS SQL DATA 
BEGIN 
DECLARE c_id INT; 
DECLARE p_id INT; 
DECLARE count INT; 
DECLARE cat_name VARCHAR(255); 
DECLARE cat_path VARCHAR(255); 
set c_id = cat_id; 
SELECT parent_category_id, category_name INTO p_id, cat_name FROM categories WHERE category_id = c_id; 
set c_id = p_id; 
set cat_path=cat_name; 
set count=0; 
WHILE (c_id IS NOT NULL) DO 

SELECT parent_category_id, category_name INTO p_id, cat_name FROM categories WHERE category_id = c_id; 
set c_id = p_id; 
set cat_path = concat_ws('>',cat_name,cat_path); 
set count = count + 1; 
IF count=10 THEN 
    SET c_id = NULL; 
END IF; 
END WHILE; 
RETURN cat_path; 
END 
$$ 
DELIMITER ; 

y luego llamar usando

select getcategory(category_id); 

Herre en esta función que he hecho una comprobación de validez a fin de evitar bucles infinitos ..

+1

Esto descubre la ruta para una sola categoría, así que si buscas un árbol, esto requeriría llamar a esto para cada resultado ... Pero bueno de todos modos;) – poncha

+0

es solo un prototipo, puedes modificar aún más esto un procedimiento, con un cursor y bucles a cada categoría árbol ... y continuar ... creo que se puede hacer – satdev86

Cuestiones relacionadas