分享一个case when then when then end的sql语句编写用法

写作背景

平时我用case when then else end的机会也不多,之前用它来做对select结果进行计算,例如:

select job,ename,(case job when 'MANAGER' then sal*1.1 when 'SALESMAN' then sal*1.5 else sal*1.8 end) as "newSal" from emp;

上面sql语句的作用是判断job字段的值,然后根据不同的值来计算薪水

今天我在看若依项目,看到里面对部门结构树的移动操作,虽然实际上是修改部门所属组织机构操作,但背后隐藏的是树中结构的移动操作,由于若依在定义部门表的时候添加了一个ancestors字段,其实也就是path字段,存储的是从最高级到当前级别的路径id字符串组合(中间用英文逗号分隔),所以我们在更改某一个部门所属父级的时候,不仅要更新改部门的ancestors字段,也要更新该部门所有子部门的所有ancestors字段,我们看一下页面吧,如下:

在这里插入图片描述
按照上图可以看出,我们要将研发中心下面的长沙分公司移动到若依科技下面,但是长沙分公司下面还有两个子级部门,按照上面的说法,我们不仅需要修改长沙分公司ancestors字段(类型path,全路径id字符串组合),也要更新该部门所有子部门的所有ancestors字段

我和若依的前一部分相同思路

先根据部门id找到长沙分公司以前的ancestors字段值,然后在获取长沙分公司最新的ancestors字段值(先获取到最新父级ancestors字段值,再加上父级id,这就是长沙分公司最新的ancestors字段值了)

根据长沙分公司的id找到所有的子级数据,然后根据上面获取到长沙分公司的新老ancestors字段值进行replace替换

现在我们拿到了所有子级部门最新ancestors字段值,代码逻辑如下:

List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
for (SysDept child : children)
{
    
    
    child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
}

我的后续解决思路(不建议)

如果是我的话,我估计会根据部门id去挨个更新,这种方式会和数据库进行多次交互,所以不建议这么做

若依后续解决思路(建议)

直接使用一个update语句更新所有的数据,我们先来看一下代码吧,如下:

java代码:

List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
for (SysDept child : children)
{
    
    
    child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
}
if (children.size() > 0)
{
    
    
    deptMapper.updateDeptChildren(children);
}

sql文件.xml:

<update id="updateDeptChildren" parameterType="java.util.List">
	update sys_dept set ancestors =
	<foreach collection="depts" item="item" index="index"
		separator=" " open="case dept_id" close="end">
		when #{
    
    item.deptId} then #{
    
    item.ancestors}
	</foreach>
	where dept_id in
	<foreach collection="depts" item="item" index="index"
		separator="," open="(" close=")">
		#{
    
    item.deptId}
	</foreach>
</update>

我们来看一下具体的sql长啥样,如下:

update sys_dept set ancestors = case dept_id when ? then ? when ? then ? end where dept_id in ( ? , ? )

通过上面的sql可以看到,首先先通过where条件找到所有需要更新的数据,然后在更新的时候通过判断dept_id的值在决定ancestors的值,所以一句sql语句可以解决所有的子级分类更新问题,是不是很nice呢

目前若依持久层框架使用的是mybatis,如果我们使用mybatis-plus,那可以使用baseMapper.updateBatchById()方法进行批量更新操作

若依后续解决思路举例

针对上面的情况我们举一个demo吧,假设原有数据长这样:

在这里插入图片描述
我们想把所有sex值为男的age值更新成20,sex值等于女的age值更新成18,sql语句如下:

update t_user 
set age =
	case sex 
		when "男" THEN 20 
		when "女" THEN 18 
	end

最终结果如下,愿望达成

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42449963/article/details/130977846