2012-03-27 7 views
6

Si tratta di un follow-up alle mie domande qui:
How to implement a many-to-many hierarchical structure in MySQL
e qui:
How to record sequential collections of records in MySQL.Come aggiungere un ordinamento a una tabella di chiusura MySQL che rappresenta una relazione molti-a-molti?

In breve, voglio implementare in MySQL una tabella di ricette e un'altra di istruzioni. Una ricetta è una serie sequenziale di istruzioni o altre ricette. Quindi, ad esempio, puoi immaginare una ricetta Peach_preserve e una Peach_tart che utilizza lo Peach_preserve, più una serie di altri passaggi (istruzioni). Peach_preserve potrebbe essere utilizzato per molte altre ricette.

Ho letto this blog post by Bill Karwin about closure tables e ritengo che questa soluzione risolva al meglio le mie sfide (la mia gerarchia è molti-a-molti e i passaggi sono sequenziali). Così, per esempio avrei:

recipe 
id name 
1 Peach preserve 
2 Cubed peeled peaches 
3 Fresh peaches 
4 Powdered sugar 
5 Cook together 
6 Peel and cut in chunks 
7 Mix 

step (or instruction) 
id desc 
1 Cook together 
2 Buy peaches 
3 Buy sugar 
4 Peel and cut in chunks 
5 Mix 

recipe_instruction 
(Ancestor) (Descendant) 
recipe_id step_id depth descendant_is_instruction 
3   3   0  0 
3   2   1  1 
4   4   0  0 
4   3   1  1 
6   6   0  0 
6   4   1  1 
2   2   0  0 
2   3   1  0 
2   2   2  1 
2   6   1  0 
2   4   2  1 
(and so on...) 

io non sono un fan della bandiera descendant_is_instruction, ma io non so come altro fare questo. Suppongo che potrei sostituirlo con un descendant_is_leaf per identificare gli elementi terminali ...

L'ordinamento è rappresentato da una tabella che incorpora tutte le relazioni ad una profondità di 1:

Depth=1 table 
recipe_id step_id  order 
3   2   1 
4   3   1 
6   4   1 
2   3   1 
2   6   2 

sto semplificando qui perché in pratica separerei gli ingredienti e le istruzioni, ma tu hai l'idea.

Quindi, è un buon modo per combinare sia una struttura gerarchica dei dati che una nozione di ordine dei passi? Qualunque cosa dovrei fare per migliorare/semplificare?

risposta

0

Così ho fatto qualche ricerca sul mio problema, sfruttando principalmente le informazioni fornite qui e altrove da Bill Karwin (alla fine ho deciso di acquistare il suo libro). Sulla base di ciò, ritengo che l'opzione migliore sia quella di aggiungere una colonna di breadcrumb alla mia tabella di chiusura, in modo simile a ciò che Bill raccomanda qui MySQL Closure Table hierarchical database - How to pull information out in the correct order.

Il pane grattugiato mi consentirebbe di ORDER BY, che risolverebbe il mio problema di ordinazione.

Vorrei trovare i nodi terminali interrogando la tabella di chiusura, cercando tutti i nodi che non hanno antenato diverso da loro.

0

Posso essere lontano da qui, ma Ricetta e istruzioni potrebbero essere la stessa tabella, semplificando le relazioni.

Istruzione: id, nome, is_recipe

Passi: parent_id, child_id, ordine

Ora una ricetta può avere istruzioni e le ricette come i bambini. Un'istruzione potrebbe anche essere di seguire una ricetta, ma con il burro ridotto ...

Potrebbe essere necessario aggiungere un po 'loop di controllo anche se ...

8

Una ricetta è una serie sequenziale di istruzioni o altre ricette .

A seconda di come si legge questa frase, questo può essere ambiguo.

ne dite:

Una ricetta è una serie sequenziale di istruzioni.

Un'istruzione è semplice (una foglia) o complessa (utilizza un'altra ricetta).

che dà:

Table recipe: 
- column id 
- column name 
- column total_cost, total_preparation_time, etc 

Table instruction: 
- column id 
- column recipe_id 
- column step_order 
- column description 
- column child_recipe_id (can be NULL) 

Quindi, se la crostata di pesche utilizza pasta e pesca conservano:

select * from recipe order by id; 
id  name 
1  Dough 
2  Peach preserve 
3  Peach tart 

select * from instruction order by recipe_id, step_order; 
id recipe_id step_order description  child_recipe_id 

100  1  1  Get flour  NULL 
101  1  2  Add water  NULL 
102  1  3  Mix together NULL 

201  2  1  Peel peaches NULL 
202  2  2  Cube peaches NULL 
203  2  3  Add sugar  NULL 
204  2  4  Cook together NULL 

301  3  1  Pre heat oven NULL 
302  3  2  Prepare dough 1 
303  3  3  Prepare peach 2 
304  3  4  Bake   NULL 

non ci sono "è foglia" bandiere.

Un'istruzione è una foglia se non indica una ricetta figlio, ad esempio child_recipe_id è NULL.

+0

In questo senso, i campi 'description' /' name' sono ridondanti l'uno rispetto all'altro. Che ne dici di avere un tavolo con l'albero delle ricette e l'altro solo i nomi? – Yuval

+0

@Yuval, non vedo il nome della ricetta e la descrizione dell'istruzione che utilizza la ricetta come ridondante. Il primo descrive "cosa" l'ingrediente risultante è (ad esempio, "cioccolato fuso"), il "come" viene utilizzato il risultato (ad esempio, "disegna l'arte nel piatto con il cioccolato fuso"). Yumm. –