Solution
PosgreSQL, Oracle, MS-SQL, ... have WITH RECURSIVE
to handle such data structures. It internally uses a while loop to get all the parent ids
for the current row (we need the child's here instead)
This can achieved in MySQL
too, you can create a stored procedure
and reproduce the same behavior
Assumed/DDL used
content_has_content
has entries as
content_1
content_2
content_3
content_4
I pass the id_content
as 2 and get the output as
content_2
content_3
content_4
All of the above are descendants of content_2
Fire call content_details(2);
to get all the child rows for the passed id_content
SQL
###### Stored Routine
DELIMITER //
drop procedure IF EXISTS `content_details`;
CREATE DEFINER=`root`@`localhost` PROCEDURE `content_details`(`_idcontent` INT)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE temp_content_ids varchar(200);
DECLARE idcontent, idcontent2 integer;
SET temp_content_ids= _idcontent;
SET idcontent = _idcontent;
SET idcontent2 = _idcontent;
WHILE idcontent2 IS NOT NULL DO
SET idcontent = NULL;
SELECT id_subcontent, CONCAT(id_subcontent,',',temp_content_ids) INTO idcontent, temp_content_ids FROM content_has_content WHERE id_content = idcontent2;
SET idcontent2 = idcontent;
END WHILE;
SELECT my_string1 FROM content WHERE FIND_IN_SET( id, temp_content_ids );
END//
What I basically do is run a while loop
until I have the last child_id
, store these ids
in a comma separated string format
and then fire a query to get all the rows which have a id
present in the var
I just created
Note: There are chances you could be having invalid values within your tables, such as row having a id_subcontent
, which points to its own id_content
, which could cause a never ending loop
within the procedure, to avoid such situations, you can use a counter and limit the nesting to say around 50 (or any value as per your requirement) and raise a exception
if that limit is surpassed
Some data to play with..
###### DLL Statements
CREATE TABLE content
( id_content int,
my_string1 varchar(200));
CREATE TABLE content_has_content
( id_content int,
id_subcontent int);
CREATE TABLE topic_has_content
( id_topic int,
id_content int);
INSERT INTO content VALUES (1, 'content_1'), (2, 'content_2'), (3, 'content_3'), (4, 'content_4');
INSERT INTO content_has_content VALUES (1, 2), (2, 3), (3, 4);
INSERT INTO topic_has_content VALUES (1, 1);
Hope this helps..