说起排序,应该是每个程序员的最基本功底了,至少冒泡排序都会吧,但今天讲的和那些排序算法没多大关系。主要是最近做一个客服系统,需要对常见问题进行排序,要求可以拖拽修改顺序,这种功能确实烂大街了啊,像这样子输入数字改变排序的:
还有像这样拖拽改变顺序的:
,事实上常见问题就是像这样的:
在后台看上去大概是这样:
需求是这样的:
拿到需求文档的那一刻我脑海里马上冒出了上家公司拖拽排序**规则的样式,心里也大概有谱了,其实很简单,不管你怎么拖拽,我只管拿到全部的guid/id的List(按顺序排好的)然后全量去修改排序的这个字段就好了 ,但也带来了几个问题:第一:无法避免的高并发情况下出现的排序混乱风险,当然幸好一般这种需求都不会涉及到高并发场景,更何况我现在只想着这么实现这个功能先,不过在同事的指导下,有了使用SQL完成该功能的方法,这个后面再讲;第二:全量更新带来的性能问题,相信很多人知道怎么批量插入,但不知道批量修改吧,像我上家公司就很蠢的用for循环一遍一遍用id对应去更新,真的很蠢,就像我在《做程序员到现在踩过的坑》中讲到的:别在for循环里一遍一遍查数据库...原因当然很简单,数据量一旦很多,数据库连接就会爆掉的,想象一下,你有几百万数据需要更新就去执行几百万条SQL,建立几百万条数据库连接,那场景太美我不敢想,所以能用一条SQL解决的就用一条SQL解决,能只建立一次数据库连接,就不要重复建立无关紧要的数据库连接,当然慢SQL不在此列。
这里贴一下批量插入和批量更新的SQL,希望有借鉴意义:
好了,讲了这么多废话,讲讲我的解决思路吧,首先我不要前端排好的序列,而是只要修改的那条常见问题和要改到哪个位置,然后代码逻辑如下:
看代码,思路应该很清晰了吧?就是把要改变位置的那条记录从数据库查出来的列表里先排除出去,然后,将剩下的队列以目标位置分为两个部分将要改变位置的那条记录插入目标位置组成全新的队列,重新生成序号然后用一条SQL批量更新序号字段,新增的话就是这样:
修改就是直接组对象调sort方法就可以了,删除我是先删除,然后全部查出来重新排序修改就可以了,像这样:
接下来将考虑使用同事提到的利用SQL原子性方法来实现同样的功能:
UPDATE table
set LEVEL =
(
CASE
WHEN (LEVEL>3 AND LEVEL<=6) THEN LEVEL-1
WHEN LEVEL=3 THEN 6
ELSE LEVEL END
)
UPDATE table
set LEVEL =
(
CASE
WHEN (LEVEL<6 AND LEVEL>=3) THEN LEVEL+1
WHEN LEVEL=6 THEN 3
ELSE LEVEL END
)