I am working on infinite level comment-reply system. And getting parent-child relative data rows successfully but I am having trouble ordering this rows.
This being used for create results: https://stackoverflow.com/a/5291159/4894502
And I have results like this;
comment_id comment parent_id depth rel_path rating
38 Com 1 0 0 0 0
39 Com 2 0 0 0 10
40 Com 3 0 0 0 0
41 Com 1-1 38 1 0/38 0
42 Com 2-1 39 1 0/39 0
44 Com 2-2 39 1 0/39 2
46 Com 3-1 40 1 0/40 0
43 Com 2-1-1 42 2 0/39/42 0
47 Com 2-2-1 44 2 0/39/44 0
45 Com 2-1-1-1 43 3 0/39/42/43 0
But ordering is problem, desired ordering is every child must be under of its parent ans children must be ordering in between according to some parameter for example rating
. So desired result like this;
comment_id comment parent_id depth rel_path rating
38 Com 1 0 0 0 0
41 Com 1-1 38 1 0/38 0
39 Com 2 0 0 0 10
42 Com 2-1 39 1 0/39 0
43 Com 2-1-1 42 2 0/39/42 0
45 Com 2-1-1-1 43 3 0/39/42/43 0
44 Com 2-2 39 1 0/39 2
47 Com 2-2-1 44 2 0/39/44 0
40 Com 3 0 0 0 0
46 Com 3-1 40 1 0/40 0
Or like this (+ order by rating)
comment_id comment parent_id depth rel_path rating
39 Com 2 0 0 0 10
44 Com 2-2 39 1 0/39 2
47 Com 2-2-1 44 2 0/39/44 0
42 Com 2-1 39 1 0/39 0
43 Com 2-1-1 42 2 0/39/42 0
45 Com 2-1-1-1 43 3 0/39/42/43 0
38 Com 1 0 0 0 0
41 Com 1-1 38 1 0/38 0
40 Com 3 0 0 0 0
46 Com 3-1 40 1 0/40 0
Example on Db Fiddle https://www.db-fiddle.com/f/uk3ZDLdD8N5tvhzb9S6rXC/1
Example Table:
CREATE TABLE `comment` (
`comment_id` int(11) NOT NULL,
`parent_id` int(11) NOT NULL DEFAULT '0',
`depth` int(4) NOT NULL DEFAULT '0',
`comment` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`rating` int(4) NOT NULL DEFAULT '0'
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
INSERT INTO `comment` (`comment_id`, `parent_id`, `depth`, `comment`, `rating`) VALUES
(42,39, 1,'Com 2-1', 0),
(41,38, 1,'Com 1-1', 0),
(40,0, 0,'Com 3', 0),
(39,0, 0,'Com 2', 20),
(38,0, 0,'Com 1', 0),
(43,42, 2,'Com 2-1-1', 0),
(44,39, 1,'Com 2-2', 2),
(45,43, 3,'Com 2-1-1-1', 0),
(46,40, 1,'Com 3-1', 0),
(47,44, 2,'Com 2-2-1', 0);
ALTER TABLE `comment`
ADD PRIMARY KEY (`comment_id`),
ADD UNIQUE KEY `comment_id` (`comment_id`);
ALTER TABLE `comment`
MODIFY `comment_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=48;
Procedure (nearly same as answer in link above):
delimiter #
create procedure comment_hier
(
in param_parent_id smallint unsigned
)
BEGIN
DECLARE v_done TINYINT unsigned default 0;
DECLARE v_depth SMALLINT unsigned default 0;
CREATE TEMPORARY TABLE hier(
comment_id int(11) unsigned,
parent_id int(11) unsigned,
depth int(99) unsigned default 0,
relation_path varchar(360) default 0
)engine = memory;
INSERT INTO hier SELECT comment_id, parent_id, v_depth, 0 FROM comment a WHERE a.parent_id = param_parent_id;
CREATE TEMPORARY TABLE tmp engine=memory SELECT * FROM hier;
while not v_done do
if exists( select 1 from hier h inner join comment a on h.comment_id = a.parent_id and h.depth = v_depth) then
insert into hier
select a.comment_id, a.parent_id, v_depth + 1, CONCAT_WS('/', relation_path, a.parent_id) from comment a
inner join tmp t on a.parent_id = t.comment_id and t.depth = v_depth;
set v_depth = v_depth + 1;
truncate table tmp;
insert into tmp select * from hier where depth = v_depth;
else
set v_done = 1;
end if;
end while;
select
a.comment_id,
a.comment as comment,
a.parent_id as parent_id,
h.depth,
h.relation_path,
a.rating as rating
from
hier h
left join comment a on h.comment_id = a.comment_id
ORDER BY h.depth, a.comment_id;
DROP TEMPORARY TABLE if exists hier;
DROP TEMPORARY TABLE if exists tmp;
END #
Run:
delimiter ;
call comment_hier(0);
I've been working for hours but I couldn't solve this. Thanks.