This should be simple enough, but i’m apparently having a Friday Morning.
I have an adjacency model table:
id INT,
name VARCHAR,
lft INT,
rgt INT
I need to select all nodes in the table (Optional, but desired: Skipping the Root node.) , and retrieve ONLY their immediate parent, because the display model requires a (id,name,parent) tuple with a unique id.
The following pulls a row for every ancestor:
SELECT node.id id, node.name name, parent.id parent
FROM mytable AS node,
mytable AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND node.lft != parent.lft
ORDER BY node.lft;
My brain keeps trying to do GROUP BY, but that doesnt tie the parent row’s columns together.
SELECT node.id id
, node.name name
, parent.id parentID
, parent.name parentName
FROM mytable AS node
INNER JOIN mytable AS parent ON node.lft = parent.id
WHERE node.rgt = 1
ORDER BY node.lft;
This should skip the root since there will be no parent info. Not sure the order makes sense (maybe parent.id, node.id would make more sense?)
you take a row and search for another row where left ist smaller then actual left and right is greater then the actual right. For this you will ge multiple results. From this results you search for the one with the smallest left, This must be your parent.
Smallest Right, or Largest Left would be your immediate parent.
For All Entries in the Table, Find The Row Which:
My Left(or right, either works) is Between Your Left and Right, Uninclusive. (“I am a descendant of you”)
Has the closest (Left/Right) to my (Left/Right) (“My Immediate Parent”)
(EDIT: If you dont make the first condition uninclusive, the “immediate parent” is the node itself.)
I don’t think you can go the way getting the child from the parent. With your logic you will get all rows of your example table when the actual row is root. But you will never know, that node2 has node1 as parent as this is not part of the result.
I guess you need to go other way around. Get the parent of the row by fetching the row with left < actual left and right > actual right (is a parent) and only take the one with the smallest left (direct parent)
If I start at Node2, and find all rows where L < 3 and R > 4, I get Node1 and Root.
The “smallest left” is Root, because 1 is the smallest. But the immediate parent is Node1. you need the largest left.
Yeah… it’s just i dont automatically think about a scalar evaluating per-row? Like, “42” is a fixed value. And normally when you want to combine two sets of data, it’s a join between tables.
Selecting a “scalar” in this case to me doesnt… really feel like you’re selecting a scalar, because you’re actually effectively pulling a vector - a single column of per-row results that relies upon a parameter (the row’s id in this case)
In truth, it’s probably more accurate to say its no different than pulling a simple formula (like say, somecolumn + 4 ), but it feels different than that because you’re selecting? I dunno.
if your subquery returns more than one row, and it’s supposed to be a scalar subquery, instead of a true column of multiple rows which you might use with IN (subquery), then you get a “your subquery has returned more than one row” error message