I have a table similar to this:
=================
| Id | ParentId |
=================
| 1 | 0 |
-----+-----------
| 2 | 1 |
-----+-----------
| 3 | 0 |
-----+-----------
| 4 | 3 |
-----+-----------
| 5 | 3 |
-----+-----------
| 6 | 0 |
-----+-----------
| 7 | 6 |
-----+-----------
| 8 | 7 |
-----------------
Given an Id, I need to know its root "node" Id. So,
There is no limit to the levels of the hierarchy. Is there a SQL that can do what I need?
Actually, you can quite easily do this using a function.
Try running the following .sql script on your favorite empty test database.
--
-- Create the `Nodes` table
--
CREATE TABLE `Nodes` (
`Id` INT NOT NULL PRIMARY KEY
,`ParentId` INT NOT NULL
) ENGINE=InnoDB;
--
-- Put your test data into it.
--
INSERT INTO `Nodes` (`Id`, `ParentId`)
VALUES
(1, 0)
, (2, 1)
, (3, 0)
, (4, 3)
, (5, 3)
, (6, 0)
, (7, 6)
, (8, 7);
--
-- Enable use of ;
--
DELIMITER $$
--
-- Create the function
--
CREATE FUNCTION `fnRootNode`
(
pNodeId INT
)
RETURNS INT
BEGIN
DECLARE _Id, _ParentId INT;
SELECT pNodeId INTO _ParentId;
my_loop: LOOP
SELECT
`Id`
,`ParentId`
INTO
_Id
,_ParentId
FROM `Nodes`
WHERE `Id` = _ParentId;
IF _ParentId = 0 THEN
LEAVE my_loop;
END IF;
END LOOP my_loop;
RETURN _Id;
END;
$$
--
-- Re-enable direct querying
--
DELIMITER ;
--
-- Query the table using the function to see data.
--
SELECT
fnRootNode(`Nodes`.`Id`) `Root`
,`Nodes`.`Id`
,`Nodes`.`ParentId`
FROM `Nodes`
ORDER BY
fnRootNode(`Nodes`.`Id`) ASC
;
-- EOF
Output will be:
Root Id ParentId
==== ==== ========
1 1 0
1 2 1
3 3 0
3 4 3
3 5 3
6 6 0
6 7 6
6 8 7
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With