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
While I would recommend revisiting your data architecture, I'll try to help you get this particular problem solved.
First, let's revisit JOIN
s. 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