Between Adjacency List Model and Nested Set Model

There is a time in your project when you need to represent some hierarchical data and the database engine happens to be MySQL and not MSSQL which by the way supports recursive CTEs! and recursive functions.
Now, there is a simple and easy way to represent the hierarchical data, which is fast at insert/update operations and slow at select operations (recursion bleah!) :

Category(
id    INT, PRIMARY KEY, AUTO INCREMENT
name    VARCHAR(50), NOT NULL
parent  INT, NULL
)

..and there is the opposite of the first solution (no recursion, fast select):

Category(
id    INT, PRIMARY KEY, AUTO INCREMENT
name    VARCHAR(50), NOT NULL
lft  INT, NOT NULL
rgt  INT, NOT NULL
)

I will concentrate on the second solution, and just to be sure you get the idea, I will attach an image with a full structure of categories:

The blue text represents the depth of the category and the red text represents the lft and rgt database fields. The green text represents the number of products in the category. You’ll see that if “Portable electronics” has 4 products, the sum of it’s child categories must be equal to 4 (“MP3 Players” + “Flash” + “CD Players” + “2-Way Radios”).
Before you choose the second solution to implement, you should be aware of the complexity of the queries and the conditions for the CRUD operations.
A quick look at the:
- update condition, when moving a category in another category (PHP syntax):

- select statement for categories and number of products (MySQL sytanx):

SELECT
`parent`.`id`,
`parent`.`name`,
`parent`.`visible`,
(
SELECT
COUNT(id)
FROM
categories
WHERE
rgt = lft + 1
AND id = parent.id
)AS is_leaf,
(
SELECT
(COUNT(parent_sub. NAME) - 1)
FROM
categories AS node_sub,
categories AS parent_sub
WHERE
node_sub.lft BETWEEN parent_sub.lft
AND parent_sub.rgt
AND node_sub.id = parent.id
GROUP BY
node_sub.id
ORDER BY
node_sub.lft
)AS depth,
COUNT(products.id)AS products_count
FROM
`categories`
CROSS JOIN .`categories` AS `parent`
INNER JOIN .`products`
INNER JOIN `categories_products` ON products.id = categories_products.product_id
WHERE
(
categories.lft BETWEEN parent.lft
AND parent.rgt
)
AND(
categories.id = categories_products.category_id
)
AND(categories.store_id = 1)
GROUP BY
`parent`.`id`,
`parent`.`visible`
ORDER BY
`parent`.`lft` ASC
LIMIT 100

and the result..

…and if you want to wrap it nicely, in a tree control, it should look like this:

So the conclusion (from the perspective of a .NET / C# developer and a PHP / Zend Ninja wannabe :) ? Doesn’t matter if you work with MySQL, SQL Server, PHP, Zend, .NET C#, you can always find a way to get the best of it.