Domanda

Si supponga che una struttura ad albero è implementato in SQL come questo:

CREATE TABLE nodes (
    id INTEGER PRIMARY KEY,
    parent INTEGER -- references nodes(id)
);

Anche se i cicli possono essere creati in questa rappresentazione, supponiamo che non abbiamo mai lasciare che accada. La tabella memorizzare solo un insieme di radici (record in cui genitore è nullo) e dei loro discendenti.

L'obiettivo è quello, dato un id di un nodo sul tavolo, trovare tutti i nodi che sono discendenti di esso.

A è un discendente del B se A 's genitore è B o A 's genitore è un discendente di B . Si noti la definizione ricorsiva.

Ecco alcuni dati di esempio:

INSERT INTO nodes VALUES (1, NULL);
INSERT INTO nodes VALUES (2, 1);
INSERT INTO nodes VALUES (3, 2);
INSERT INTO nodes VALUES (4, 3);
INSERT INTO nodes VALUES (5, 3);
INSERT INTO nodes VALUES (6, 2);

che rappresenta:

1
`-- 2
    |-- 3
    |   |-- 4
    |   `-- 5
    |
    `-- 6

Siamo in grado di selezionare i bambini (immediati) di 1 in questo modo:

SELECT a.* FROM nodes AS a WHERE parent=1;

Possiamo selezionare i figli ei nipoti di 1 in questo modo:

SELECT a.* FROM nodes AS a WHERE parent=1
UNION ALL
SELECT b.* FROM nodes AS a, nodes AS b WHERE a.parent=1 AND b.parent=a.id;

Possiamo selezionare i figli, nipoti e pronipoti di 1 in questo modo:

SELECT a.* FROM nodes AS a WHERE parent=1
UNION ALL
SELECT b.* FROM nodes AS a, nodes AS b WHERE a.parent=1 AND b.parent=a.id
UNION ALL
SELECT c.* FROM nodes AS a, nodes AS b, nodes AS c WHERE a.parent=1 AND b.parent=a.id AND c.parent=b.id;

Come può una query essere costruito che ottiene tutti i discendenti di 1 nodo piuttosto che quelli a una profondità fissa? Sembra che avrei bisogno di creare una query ricorsive o qualcosa del genere.

Mi piacerebbe sapere se tale richiesta una sarebbe possibile utilizzando SQLite. Tuttavia, se questo tipo di query richiede non funzionalità disponibili in SQLite, sono curioso di sapere se si può fare in altri database SQL.

È stato utile?

Soluzione

Alcuni database permettere che l'uso di ricorsive espressioni di tabella comune, ma non SqlLite.

Si potrebbe pensare di cambiare la tua definizione di tabella. Con una tabella come questa, è facile per interrogare tutti i discendenti di 1:

id (varchar)
--------------
001
001002
001002003
001002003004
001002003005
001002006

Questo consente di interrogare tutti i discendenti di 1 come:

select * from YourTable where id like '001%'

Sembra un po 'sgargianti, ma funziona molto bene nella pratica.

Altri suggerimenti

Il modo in cui hai impostato lo schema in realtà non soddisfare sé molto bene al modello relazionale (come hai scoperto). Ma c'è un altro modo che potrebbe non essere così evidente in un primo momento, ma è molto più flessibile. Si chiama un "modello set nested" e le strutture giuste cose in modo leggermente diverso.

Gestione dati gerarchici in MySQL (look per la sezione "The Set modello Nested") mostra come fare questo in MySQL, ma dovrebbe tradursi in SQLite abbastanza facilmente. Non voglio entrare troppo nel dettaglio qui, perché questo articolo è in realtà piuttosto lunga, ma dovrebbe darvi tutto ciò che serve per andare avanti.

Oracle ha una sintassi CONNECT BY che potrebbe essere utilizzato per questo, ma naturalmente è specifico per Oracle.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top