提前首先说明一下,这篇文章单纯的是做记录用,方便以后自己查看。如有任何问题,概不解答,因为我没遇到。我对sql这一块也不是了解得很好。
首先说一下遇到的需求:
实际需求是这样的,用户与管理员表是不同的,然后评论表里有一个user_id字段和一个is_admin字段,根据判断is_admin字段的值,去对应管理员/用户表里查询对应的用户数据。
表结构如下:
id | content | user_id | is_admin | pid |
1 | 内容1 | 1 | 0 | null |
2 | 内容2 | 1 | 1 | 1 |
3 | 内容3 | 1 | 0 | 2 |
4 | 内容4 | 1 | 1 | 3 |
id | user_nickname |
1 | 张三 |
id | name |
1 | 李四 |
总的来说就这三张表,要用sql去实现上述需求,当时我也是没遇到过sql判断的情况,就去论坛里问了下大神,还是得到了解决。
sql如下:
SELECT pinglun.id,pinglun.content,IFNULL(user_wechat.user_nickname,sys_user.name) AS name
FROM pinglun
LEFT JOIN user_wechat
ON user_wechat.id = pinglun.user_id
AND is_admin = 0
LEFT JOIN sys_user
ON sys_user.id = pinglun.user_id
AND is_admin = 1;
思路解析:
这里大神是用了mysql里的函数IFNULL,如果为空则返回第二个参数,即sys_user.name.,下面是左连接操作。
我们如果把IFNULL去掉,就会发现有些地方是null的,这是由于左连接的时候把is_admin=0等给加入了连接的on条件里。
这里用IFNULL就能实现这个功能了。
这里扩展一下,因为本来的实际需求是还要根据后面的pid去查询对应的包含自身的子节点。
这里贴一下当时看的帖子的链接:查询子节点
就不过多去说明了,里面其实写得挺细致的。我这里做一下针对自身的扩展。
即传入一个评论id,去查询对应评论id的包含自身的子节点,然后根据这个评论里的is_admin去查询对应不同表的用户/管理员信息。最后汇总。
SELECT w.id,w.content,IFNULL(user_wechat.user_nickname,sys_user.name) AS name,w.is_admin,w.pid
FROM (select id,user_id,pid,is_admin,content from (
select t1.id,t1.is_admin,t1.user_id,t1.pid,t1.content,
if(find_in_set(pid, @pids) >0, @pids := concat(@pids, ',', id), 0) as ischild
from (
select id,is_admin,content,user_id,pid from pinglun t order by pid, id
) t1,
(select @pids := 1) t2
) t3 where ischild !=0 or id = 1) w
LEFT JOIN user_wechat
ON user_wechat.id = w.user_id
AND w.is_admin = 0
LEFT JOIN sys_user
ON sys_user.id = w.user_id
AND w.is_admin = 1;
当时写下来就这么长,大概思路就是把查询子节点的数据,当成一张独立的表,然后根据这个表再去做IFNULL判断即可。
总结:
这个时候记录一下,其实这个功能,可以重新思考一下思路,我们现在的实现是纯sql语句来实现这个功能的,我也不太清楚这样做是不是好事。
不过实现起来确实过于复杂,虽然写起来很爽就是了。可是能遇见后期维护起来可能会很麻烦看到这么长这么复杂的sql语句。
所以这里其实可以这样来实现这个功能:
首先我们只需要按照第二步的sql去查询对应的包含自身的子节点。根据里面查找到的is_admin,在后台逻辑部分做一下处理,把is_admin和user_id传入工厂,我们由工厂去处理这一块问题,工厂判断如果is_admin是0,则访问某个接口,如果是1,则访问另外的接口即可。
或者在dao层接受第一次查询到的节点数据。mapper写的时候做一下if判断也可以实现。
不过这样的话会多次访问数据库,造成一些损耗。
所以总的来说,我也不知道哪个方法比较好,因为没有详细对比过,因为我这段sql语句,虽然只有一次访问,不过里面的耗时不一定就比多次访问简单sql快。
而且维护起来十分麻烦。