【发布时间】:2019-01-10 11:33:44
【问题描述】:
我正在开发无限级别的评论回复系统。并成功获取父子相关数据行,但我无法订购这些行。
这用于创建结果:https://stackoverflow.com/a/5291159/4894502
我有这样的结果;
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
但是排序是个问题,期望的排序是每个孩子都必须在其父母之下,孩子必须根据一些参数在两者之间排序,例如rating。所以想要这样的结果;
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
或者像这样(+按等级排序)
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
Db Fiddle 示例 https://www.db-fiddle.com/f/uk3ZDLdD8N5tvhzb9S6rXC/1
示例表:
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;
程序(与上面链接中的答案几乎相同):
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 #
运行:
delimiter ;
call comment_hier(0);
我已经工作了几个小时,但我无法解决这个问题。谢谢。
【问题讨论】:
-
您可以用您的编程语言重新排序结果。你用的是哪一个?
-
我会认真审查这种设计是否最优
-
我使用 php,但如果可能的话,我想用 mysql 解决这个问题@Adder
-
@Corion db-fiddle.com/f/uk3ZDLdD8N5tvhzb9S6rXC/1 我在这里添加了代码。谢谢你的建议。我正在研究您的解决方案。
-
@Strawberry 你有什么建议吗?