问个小问题, mysql 查询所有父节点的一点小疑惑?

327 天前
 whooami
SELECT
@r AS _id,
	(SELECT @r := parent_id FROM t_category WHERE id = _id) AS parent_id,
	@l := @l + 1 AS lvl
	FROM (SELECT @r := 89, @l := 0) vars, t_category t
WHERE @r <> 0 AND parent_id >0;

如果 @r = 89 在库中是存在的,这时候结果正常 如果 @r = 89 在库中是不存在的,就会出现以下记录

_id          parent_id   lvl
89   		NULL        1
89   		NULL        2
...

再添加 and parent_id is not null 也一样输出上面的纪录。 但是如果在外面再包上一层 再判断 parent_id is not null 结果就正常了。 请教一下各位大佬这是什么问题?

还有像这种查询所有父 /子节点的需求最佳方案一般是在代码层解决,还是像这样在 sql 层解决?还有没有更好的方案?

1410 次点击
所在节点    MySQL
13 条回复
b821025551b
327 天前
(再添加 and parent_id is not null 也一样输出上面的纪录。 但是如果在外面再包上一层 再判断 parent_id is not null 结果就正常了)这是因为操作的数据集不同;直接添加的话,原记录中 parent_id 就是非空,所以加不加没效果;包一层后针对的是上层筛选过的结果集做数据集,parent_id 就是有 null ,可以正常过滤;

后面的问题,看起来不是很清晰,最好给一下表结构。
whooami
327 天前
@b821025551b 抱歉,我忽略了。表中的 parent_id>=0 的非空字段。
```
CREATE TABLE `t_category` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'pk',
`uid` bigint(20) unsigned DEFAULT '0' COMMENT '用户 ID',
`name` varchar(32) NOT NULL COMMENT '名称',
`parent_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '0 无父级',
PRIMARY KEY (`id`),
KEY `IDX_UID` (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=utf8mb4 COMMENT='总分类表';
```
byty18768
326 天前
mysql 这个递归…给我留下了深刻的印象
beijinglowb
326 天前
我们一般用 with recursive
Mumu2580
326 天前
如果层级不高的话,直接加一个字段维护 root 到本节点路线就 ok 了。如果是固定不变的层级关系,一般全查了(涉及到的全查了),在应用层整理层级然后缓存。
whooami
326 天前
@byty18768 我也是在网上查的,还要进一步理解
@beijinglowb
@Mumu2580
两位给出了另外两种方法,之前我们采用的是在应用层递归,这次新服务,想来问问那种方法比较好,看能不能精进一下?
offswitch
326 天前
1.保存此节点的所有父节点到一个数组中
2.另外维持一张节点父节点关系表
3.加载到内存中,维持好结构,避免频繁查,一条 select 查出所有节点信息即可,修改了就重新加载
1 、2 差不多
whooami
326 天前
@offswitch 嗯,这个也是现在较常用的作法。因为是多级,可以通俗理解成树形。所以如果这样分可能效果不大。比如一级节点只有 20 个,二级节点可能有 500 ,三级可能更多。变更也是根据数据热度变更的。所以在想有没有更好的办法。当然加载到内存,避免频繁查就很好。
wxf666
326 天前
@whooami 如果你不介意额外占用 10 倍空间,你可以用《闭包表》。

一条 SELECT 就能查出某个节点的所有祖先节点,而且是顺序查询,速度非常快。

我以前发过一个[帖子](/t/889443),讨论过这种数据库表结构。
beijinglowb
326 天前
@whooami 能在 sql 内解决效率最高,应用里递归慢不说,额外资源开销也很大。
whooami
326 天前
@wxf666 谢谢,也是一种思路。对于有限数据来说可能闭包表是一个方案。对于目前本身数据量在膨胀并且还没有限制的一个业务来讲可能还要进一步的考量
@beijinglowb 嗯,我也是这么想的。
Shamiko
326 天前
层级不高直接 with recursive ,高了用物化路径
whooami
324 天前
@Shamiko 简单明了, 感谢大佬

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/950386

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX