2012-07-12 12 views
6

Sto lavorando alla gestione delle categorie. Dove ho parentId con ogni riga. Le categorie possono essere di livello n. Posso chiamare ricorsivamente la funzione php che restituirà l'array dell'albero delle categorie.Query Mysql che restituisce l'albero delle categorie

enter image description here

Ora problema è: Nel pannello di amministrazione voglio pagina Inserzione categoria come illustrato di seguito. cioè in quale categoria si trova in quale.

  • casa
  • Prodotti (Edit) (Nascondi)
  • Prodotti> prodotto 1 (Edit) (Nascondi)
  • Prodotti> Prodotto 2 (Edit) (Nascondi)
  • Prodotti> Prodotto 2 > prodotto 2 1 (Edit) (Nascondi)
  • Prodotti> prodotto 2> del prodotto 2 2 (Edit) (Nascondi)
  • Contattaci (Edit) (Nascondi)

Voglio il risultato della query mysql nello stesso ordine come mostrato sopra. Non sono sicuro di come posso ottenerlo.

SELECT * 
FROM tbl_categories 
ORDER BY ??? 

Guida.

+0

Migliore utilizzo del server per esso pgoramming lingue. – Oyeme

+0

Funziona con la programmazione. Ci può essere il paging nell'inserzione, voglio usare il limite con quella query. Da qualche parte nel carrello della spesa opensource ho visto, ma non ricordo come hanno fatto. – VibhaJ

+0

per favore mostraci la struttura della tabella, cioè diciamo, voglio 2 ottenere la riga Prodotto 2.1 –

risposta

0

Non è possibile ottenere ciò in una singola query mysql. Bene, puoi ottenere questo, eseguendo più query. L'algoritmo è simile al seguente: Inizialmente creare un oggetto dataset che si popolerà, recuperando i dati dal database. Crea un metodo che prende l'id padre come parametro e restituisce i suoi nodi figli se presenti e restituisce -1, se non ha un figlio. Step1: Recupera tutte le righe, che non hanno un nodo genitore (root). Step2: Iterate attraverso questo risultato. Ad esempio se prod1 e prod2 sono i nodi restituiti iniziali, nel set di risultati. Facendo scorrere questa RS, otteniamo prod1 e inseriamo una riga nel nostro oggetto DataSET. Quindi inviamo l'id di prod1 per ottenere il metodoCHILD, per ottenere il suo figlio, e poi di nuovo iteriamo il gruppo di risultati restituito, e di nuovo chiamiamo il metodo getCHILD, finché non otteniamo il nodo più basso.

2

Non esiste una query singola SQL che può portare i risultati ordinati nel modo previsto in base a questa struttura di tabella.

Ci sono due modi per risolvere il problema:

  1. usare la logica applicazione esterna (al di fuori del DB) per effettuare chiamate ricorsive che scopriranno i bambini di ogni categoria e costruire l'albero in applicazione.

  2. Utilizzare uno degli algoritmi per la memorizzazione dei dati dell'albero in un database relazionale. Uno di questi algoritmi è chiamato Modified Preorder Tree Traversal o semplicemente MPTT.

Supponendo che utilizzano colonne lft e rgt per mantenere indici sinistra/destra in attraversamento, quando si inserisce una nuova categoria è necessario:

  1. Get categoria principale informazioni da ID: SELECT lft,rgt FROM tbl_categories WHERE categoryId=5 Supponiamo per una questione di esempio, che la categoria padre aveva lft=7 e rgt=10 (in questo caso ha già un figlio)

  2. M ake spazio per una nuova voce - spostare tutti i record da 2 (1 per LFT e 1 per 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 qui ORDER discendente. Poiché lft e rgt devono essere univoci, si consiglia di creare un vincolo UNIQUE su di essi e quindi è necessario un ordine decrescente in aggiornamento per evitare errori di chiave duplicati.

  1. Set lft=<former parent rgt> e rgt=<former parent rgt +1> e inserire un nuovo record ...

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

Si possono trovare esempi più dettagliati con il codice se si cerca MPTT PHP MySQL. Ci sono alcuni tutorial su questo argomento.

+0

grazie .. controllandolo .. – VibhaJ

+3

@VibhaJ: un'altra opzione sarebbe una tabella di chiusura: http://karwin.blogspot.de/2010/03/rendering-trees-with-closure-tables.html che ha l'ulteriore vantaggio che puoi avere chiavi esterne per assicurarti che la categoria padre esista effettivamente. –

+0

Btw, di solito uso MPTT pur mantenendo il genitore (e aggiungo anche profondità) nella tabella, quindi non ha il trabocchetto di trovare parenti stretti ... – poncha

2

è possibile utilizzare una funzione memorizzata che recupera in modo ricorsivo il percorso radice e concatena con il genitore.

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 ; 

e quindi chiamare utilizzando

select getcategory(category_id); 

Herre in questa funzione ho fatto un controllo di integrità in modo da evitare loop infinito ..

+1

Questo scopre il percorso per una singola categoria, però, quindi, se stai recuperando un albero, questo richiederebbe di chiamare questo per ogni risultato ... Comunque è bello;) – poncha

+0

è solo un prototipo, puoi anche modificarlo ulteriormente con una procedura, con un cursore e loop per ogni categoria albero .. e prosegui .. credo che si possa fare – satdev86

Problemi correlati