2010-03-14 17 views
18

Ho una semplice tabella MySQL questo è contiene un elenco di categorie, il livello è determinato dal parent_id:Ottenere tutte le righe padre nella query SQL uno

id name parent_id 
--------------------------- 
1 Home  0 
2 About  1 
3 Contact  1 
4 Legal  2 
5 Privacy  4 
6 Products 1 
7 Support  1 

sto cercando di fare un filo di Arianna. Quindi ho l''id' del bambino, voglio avere tutti i genitori disponibili (facendo scorrere la catena fino a raggiungere 0 "Home"). Potrebbero esserci numeri o righe figlio che raggiungono una profondità illimitata.

Attualmente sto usando una chiamata SQL per ciascun genitore, questo è disordinato. C'è un modo in SQL per fare tutto questo su una query?

risposta

43

Adattato da here:

SELECT T2.id, T2.name 
FROM (
    SELECT 
     @r AS _id, 
     (SELECT @r := parent_id FROM table1 WHERE id = _id) AS parent_id, 
     @l := @l + 1 AS lvl 
    FROM 
     (SELECT @r := 5, @l := 0) vars, 
     table1 h 
    WHERE @r <> 0) T1 
JOIN table1 T2 
ON T1._id = T2.id 
ORDER BY T1.lvl DESC 

La linea @r := 5 è il numero di pagina per la pagina corrente. Il risultato è il seguente:

1, 'Home' 
2, 'About' 
4, 'Legal' 
5, 'Privacy' 
+6

voi signore ... siete GENIUS !! –

+0

'+ 1' @Mark fai miracoli con query variabili: D – bonCodigo

+0

WOW ... e hanno detto che non si poteva fare! – Mike

0

credo, non c'è un modo semplice per farlo, utilizzando una query.

Vorrei raccomandare di dare un'occhiata a Nested Sets, che sembra adattarsi alle vostre esigenze.

1

Risposta straordinaria di Mark Byers!

Forse un po 'in ritardo alla festa, ma se si vuole anche per prevenire un ciclo infinito quando id = parent_id (vale a dire quando i dati sono stati danneggiati in qualche modo), è possibile espandere la risposta in questo modo:

SELECT T2.id, T2.name 
FROM (
    SELECT 
     @r AS _id, 
     @p := @r AS previous 
     (SELECT @r := parent_id FROM table1 WHERE id = _id) AS parent_id, 
     @l := @l + 1 AS lvl 
    FROM 
     (SELECT @r := 5, @p := 0, @l := 0) vars, 
     table1 h 
    WHERE @r <> 0 AND @r <> @p) T1 
JOIN table1 T2 
ON T1._id = T2.id 
ORDER BY T1.lvl DESC 
0

In aggiunta alle soluzioni di cui sopra:

post 
----- 
id 
title 
author 

author 
------ 
id 
parent_id 
name 


[post] 

id | title | author | 
---------------------- 
1 | abc | 3  | 


[author] 

| id | parent_id | name | 
|---------------------------| 
| 1  | 0   | u1 | 
| 2  | 1   | u2 | 
| 3  | 2   | u3 | 
| 4  | 0   | u4 | 

un autore tra cui i genitori possono avere un accesso al post.

Voglio verificare se l'autore ha accesso al post.

Soluzione:

danno id del post dell'autore e restituire tutti i suoi autori e dei genitori dell'autore

SELECT T2.id, T2.username 
FROM (
    SELECT @r AS _id, 
     (SELECT @r := parent_id FROM users WHERE id = _id) AS parent_id, 
     @l := @l + 1 
    FROM 
     (SELECT @r := 2, @l := 0) vars, 
     users h  
    WHERE @r <> 0) T1 JOIN users T2 
ON T1._id = T2.id; 

@r: = 2 => assegnando valore alla @r variabile.

Problemi correlati