公司是做直销系统的,因为业务需要,给客户做一个双轨会员制系统设计。里面会员关系用到了左右值数计算。
双轨就是,每个节点只允许最多有两个直接子节点。
左区,就是某个节点下面左边的节点列表
右区,就是某个节点下面右边的节点列表
要结算对碰奖金,我现在需要计算出以某层为根节点,能够获得第N层的左区或者右区节点数据。
我的表结构数据是这样的,
表名:kt_relation
relation_id :没啥用,一般没用他
user_id :这是会员id,我用他来记录某个节点左右区是否已经占用。
Lft:左值
Rgt:右值
Lft_sub:某会员id左区是哪个会员,没有就是0,
Rgt_sub:某会员id右区是哪个会员,没有就是0.
Level:层数,跟节点是第一层。也就是所在树中的深度。
我算出来了,以跟节点为准10001,第N层的左右区节点列表,sql语句是这样的。
Child.user_id, Child.Lft, Child.Rgt,Child.Level
FROM kt_relation as Child, kt_relation as Parent
WHERE
Child.Level = 3
AND Child.Lft+Child.Rgt <= Parent.Lft +Parent.Rgt
AND Parent.user_id = 10001
核心就是:Lft+Rgt<=Lft+Rgt,某个父亲子节点左右值之和<=父亲节点的左右值之和,那么他就是父亲节点的左区,然后我想查看第3层,看看有哪些节点。
现在我想查询,如上图黄色的user_id是10003的,这个节点,他的左区的第三层是哪些节点,应该是绿色那两个节点。现在就是卡到这里,弄不动了。
我自己的想法是,还是用上面那种sql从根节点开始,10003的第三层应该是10001的第4层,10003在10001的右区,那么我就把10001的左区都排除,只查询10001第4层的右区有多少节点,显然把10013也包含进去了。这个又堵住了,感觉行不通。即便可行,也存在一个问题。就是要好多条sql语句,才能完成最终结果。有没有办法,只用像上面那种一条就出结果的,查询耗时在0.035s,0.02s这种的语句。
因为不想在这里太耗时,后面还有很多计算奖金的查询,更新什么的,又要耗时间。尽可能查询时间短点。我都做了索引了。
不知道我说清楚没有,有大侠对左右值算法有研究的朋友,指点指点。
搞出来了一个sql语句,可以实现。前提是确认这个节点是最顶层节点10001的哪个区域,然后查10001的右区,再加个条件,查询10003的左区,12+25就能代表10003了。
这种自连接,搞的我有点晕乎!速度还可以,可能是有索引的原因。
php里面就是,先取得待查的节点10003的记录,取出他的,左右值。
然后计算出,应该查以根节点开始的哪层。比如这个10003,要查他开始的第3层,那实际查的应该是,10001的第4层。因为10003与10001差1层。所以是,3+1层。什么乱七八糟的。
搞出来个简单的,先查出这个节点的所有子孙节点,加条件,和值小于自身,再限定定层。就出来了。
SELECT * FROM Tree WHERE Lft > 1 AND Lft < 26 AND Lft + Rgt <= 1 + 26 AND Level = 4
为什么,我把问题写出来,然后不久,自己就解决了问题,好怪。不写就整不出来。其实我就是个菜b