Question

We are using a hybrid of the nested sets model to allow a child to have multiple parents. It is an expansion on the nested set model described in Mike Hillyers blog: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ - this might help explain some of the column names.

I am fairly new to SQL but I have investigated joins, subqueries etc. and nothing seems to offer me the result I need. I expect the answer is fairly simple though and will almost definitely be a LEFT JOIN but I can't put my finger on it.

I have a simple table called 'nested_parts' with 5 columns: 'tree_id', 'part_id', 'lft', 'rgt' and 'mapping'.

The following query returns the values I want to compare in the second query.

SELECT * FROM nested_parts WHERE part_id = 125

Specifically, I now know which tree_id's that part#125 exists in and the lft and rgt values for each tree_id.

I now need to know all the part_id's which are in the array of tree_id results I pulled earlier.

I used this a subquery for this:

SELECT * FROM nested_parts
WHERE tree_id = ANY (SELECT tree_id AS tbl FROM nested_parts WHERE part_id = 125)

Now I need to know which part_id's have lft and rgt values that are not between the lft and rgt values of part#125 within the scope of each tree_id. This would be easy if I had two tables to compare still, or could use virtual tables but this doesn't seem possible here without a loop.

Any help gratefully received but please appreciate that I am stupid not lazy, and although I have read plenty about UNIONS, JOINS, HAVING, WHERE, SELECT(SELECT), with the complexity of the data on top, I am finding this extremely confusing.

Kind regards,

James

Was it helpful?

Solution

While I would recommend revisiting your data architecture, I'll try to help you get this particular problem solved.

First, let's revisit JOINs. Your query

SELECT * FROM nested_parts WHERE tree_id = ANY (SELECT tree_id AS tbl FROM nested_parts WHERE part_id = 125)

can be simplified with a JOIN

SELECT np.* FROM nested_parts AS np
INNER JOIN nested_parts AS np2
ON np.tree_id = np2.tree_id
AND np2.part_id = 125

I will answer a bit more completely after I finish reading the question and fully understand it. I hope this helps for now.

UPDATE:

In order to get ONLY records where the lft and rgt values are not between the lft and rgt values from part #125, you have to use the HAVING condition.

SELECT np.* FROM nested_parts AS np
INNER JOIN nested_parts AS np2
ON np.tree_id = np2.tree_id
AND np2.part_id = 125
HAVING np.lft > np2.rgt
    AND np.rgt < np2.lft

If my logic is bad here, let me know. I think this is what you're looking for, though.

EDIT:

Your query can also combine conditions for the join

SELECT np.* FROM nested_parts AS np
INNER JOIN nested_parts AS np2
ON np.tree_id = np2.tree_id
AND np2.part_id = 125
AND np.lft > np2.rgt
AND np.rgt < np2.lft
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top