Du skulle troligen vilja göra kapslade uppsättningar. De är lite knepiga att ställa in, men gör frågorna MYCKET enklare. Så istället för kategoriförälder kommer du att ha två kolumner - lft
och rgt
. Vänster och höger är i princip gränserna för en kategori, om ett objekts kategori-id ligger mellan dessa värden vet du att det är ett underordnat objekt i den kategorin.
+----+---------------+-----+------+
| id | category name | lft | rgt |
+----+---------------+-----+------+
| 1 | cars | 1 | 24 |
+----+---------------+-----+------+
| 2 | bmw | 2 | 3 |
+----+---------------+-----+------+
| 5 | audi | 4 | 23 |
+----+---------------+-----+------+
| 6 | 100 | 5 | 6 |
+----+---------------+-----+------+
| 7 | 80 | 7 | 8 |
+----+---------------+-----+------+
| 8 | A4 | 9 | 22 |
+----+---------------+-----+------+
| 9 | TDI | 10 | 11 |
+----+---------------+-----+------+
| 10 | Quatro | 12 | 21 |
+----+---------------+-----+------+
| 11 | Black | 13 | 18 |
+----+---------------+-----+------+
| 12 | White | 19 | 20 |
+----+---------------+-----+------+
| 13 | 2 doors | 14 | 15 |
+----+---------------+-----+------+
| 14 | 5 doors | 16 | 17 |
+----+---------------+-----+------+
Sedan, för att få antalet föremål i kategorin bilar, kan du göra det superenkelt så här:
SELECT categories.name, items.id, items.category_id, items.name
FROM categories
LEFT JOIN items
ON (items.category_id BETWEEN categories.lft AND categories.rgt)
WHERE categories.category_name = 'cars'
Självklart kan du bara ändra värdet på category_name
och få föremålen i ALLA kategorier.
Ursäkta, av någon anledning roterade bilden när jag laddade upp den här, men om du ritar ut dina kategorier som cirklar och sedan numrerar linjerna kan du se vad värdet ska vara för vänster och höger.
Jag körde bara bilar eftersom jag tänkte att man kunde extrapolera för att få de andra kategorierna.
Så om du skriver ut dina kategorier så här:
Cars(BMW(), Audi(100(),80(),A4(TDI(),Quatro(Black(2dr(),5dr()), White())))
Sedan kan du märka din parentes med siffror:
Cars[1]->(BMW[2]->()<-[3], Audi[4]->(100[5]->()<-[6],80[7]->()<-[8],A4[9]->(TDI[10]->()<-[11],Quatro[12]->(Black[13]->(2dr[14]->()<-[15], 5dr[16]->()<-[17])<-[18], White[19]->()<-[20])<-[21])<-[22])<-[23])<-[24]
Eller om du kartlägger det som ett träd kan du märka det så här, där du märker noden längst till vänster med ett nummer, och bara märker den högra noden när du har märkt alla dess underordnade: