一次请求对多条数据进行排序的算法(一)

序号order从1开始的递增整数,无间断无重复

为保证序号不间断、无重复,每次修改数据的序号后,都要对其他的数据序号进行顺移。
同时移动多条数据是指保证序号不间断、无重复的情况下,一次请求中:之后的数据移动不影响之前移动过的数据的序号。
移动流程:

把数据块从位置o移动到位置n,并添加1个锁定块和1个预留位(预留位=n),锁定块不再参与移动
如果o>n:区域上移
    把m和n(包括m、n)之间的数据(排除锁定块)下移1位
    把预留位的数据下移1位,执行c次(c=预留位数量-1)
如果o<n:区域下移
    把m和n(包括m、n)之间的数据(排除锁定块)上移1位
    把预留位的数据上移1位,执行c次(c=预留位数量-1)
重复上面的步骤,直到所有数据被移动到指定的位置

示意图:

去重说明:每移动一次会产生一个预留位,下次区域顺移的时候可能会有数据被移动到预留位,这时候需要再次移动预留位上的数据,但是如果有多条相邻的预留位,移动后还是在预留位上,所以最多需要移动c次,c=预留位数量-1。

下面是一个php实例:

//要移动的数据
$rows = array(
    array(
        "id"=>3,/*唯一标识*/
        "moveto"=>8/*目标位置*/
    ),
    array(
        "id"=>4,
        "moveto"=>9
    ),
    array(
        "id"=>12,
        "moveto"=>2
    )
    ...
)
$locked = array();//锁定块数组
$lockedorder = array();//预留位数组
foreach($rows as $row){
    $o = $db->result("SELECT order FROM ".DB_TABLEPRE."user WHERE  id=$row[$id] ");//数据原来的位置o
    $n = $row[moveto];//目标位置n
    $db->query("update user set order=$n  WHERE  id=".$row[$id]);//移动该条数据

    if($n == $o){
        //不用移动
    }elseif($n > $o){
        //区域上移
        $db->query("update user set order=order-1  WHERE  id NOT IN(implode(‘,‘,$locked))  AND order>=$o AND order<=$n ");
        //执行c次排重
        foreach($locked as $temp){
            $db->query("update user set order=order-1  WHERE  id NOT IN(implode(‘,‘,$locked))  AND order>=$from AND order<=$n  AND order IN(implode(‘,‘,$lockedorder))");
        }
    }else{
        //区域下移
        $db->query("update user set order=order+1  WHERE  id NOT IN(implode(‘,‘,$locked))  AND order<=$o AND order>=$n ");
        //执行c次排重
        foreach($locked as $temp){
            $db->query("update user set order=order+1  WHERE  id NOT IN(implode(‘,‘,$locked))  AND order<=$o AND order>=$n AND order IN(implode(‘,‘,$lockedorder))");
        }
    }
    $locked [] = $row[$id];//添加一个锁定数据块
    $lockedorder [] = $n;//添加一个预留位
}
时间: 2024-10-12 07:31:21

一次请求对多条数据进行排序的算法(一)的相关文章

一次请求对多条数据进行排序的算法(二)

序号order从1开始的递增整数,无间断无重复 为保证序号不间断.无重复,每次修改数据的序号后,都要对其他的数据序号进行顺移.同时移动多条数据是指保证序号不间断.无重复的情况下,移动数据到指定位置. 移动流程 1.把数据移动到指定位置(修改序号) 标记一个空位(数据原来的位置序号) 标记一个重复位(数据移动后的位置序号) 2.对空位和重复位排序 3.移动每对空位和重复位之间的数据 空位大于重复位:下移 空位小于重复位:上移 示意图1: php实例 //要移动的数据 $rows = array(

对一千万条数据进行排序---编程珠玑第二版 第一章

本书第一章提出了一个看似简单的问题,有最多1000万条不同的整型数据存在于硬盘的文件中,如何在1M内存的情况下对其进行尽可能快的排序. 每个数字用4byte,1M即可存储250 000个数据,显然,只要每次对250 000个数据排序,写入到文件中即可,重复40次. 那么如何选出每次遍历的二十五万条数据呢?有如下两个策略: 1.对一千万条数据遍历40次,第i次遍历时,判断数是否属于[i*250000,i*250000+249999),如果是,则读入内存,当第i次遍历完成时,内 存中有了二十五万条数

请求的那一条数据,

客户端:删除一条,索引不变, 服务器:向上弹出一条,然后实时查询,就错过了一条, count = 1,pageindex = pageindex * count,代表第几页,请求的是第 几条数据,也可以根据 数组里面有几条数据 就选择加载几条数据, if (isLoadOne) { [params setObject:@"1" forKey:@"count"]; [params setObject:[NSString stringWithFormat:@"

php执行一条insert插入两条数据其中一条乱码

显然这就是编码问题,但是问题从哪来的呢, 我把文件编码以及代码的编码都设置成utf-8了,为什么还有这个问题于是我就开始写测试脚本 第一条 mysql_query('insert into table value(1,1,"思考思考123")') 测试没有问题 第二条 $name=$_GET["name"]; mysql_query('insert into table value(1,1,"'.$name.'")') 测试出问题了,数据库竟然插

ASP.NET easyUI--datagrid 通过ajax请求ASP.NET后台数据的分页查询

js前台对datagrid的定义代码,如下 mygrid = $('#mytable').datagrid({ fit: true, //自动大小 height: 'auto', rownumbers: true, //行号 fitColumns: true, collapsible: true, //是否可折叠的 loadMsg: '数据装载中......', singleSelect: true, //单行选取 pagination: true //显示分页 // columns: [[]]

为什么注册页面刷新一次,数据库就多了一条数据?????

web项目为什么点击注册按钮跳转不到注册页面?(上一篇博客) 从上次注册页面能成功访问之后(上一篇博客),我就开始编写注册页面.最终成功的将用户名和密码插入到数据库中! 但是问题百出!我登录刚刚注册的页面,系统就开始报错了!! nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), b

php+mysqli预处理技术实现添加、修改及删除多条数据的方法

本文实例讲述了php+mysqli预处理技术实现添加.修改及删除多条数据的方法.分享给大家供大家参考.具体分析如下: 首先来说说为什么要有预处理(预编译)技术?举个例子:假设要向数据库添加100个用户,按常规思路,就是向数据库发送100个执行请求,此时,按照 mysql 数据库的工作原理,它需要对每一条执行语句进行编译(这里就有100次).所以,这里的效率是非常低的. 预处理(预编译)技术的作用,就是减少编译的次数和时间,以提高效果.通过一个案例来说明,预处理(预编译)技术是如何做到的(好吧,先

一条数据的HBase之旅,简明HBase入门教程-Write全流程

如果将上篇内容理解为一个冗长的"铺垫",那么,从本文开始,剧情才开始正式展开.本文基于提供的样例数据,介绍了写数据的接口,RowKey定义,数据在客户端的组装,数据路由,打包分发,以及RegionServer侧将数据写入到Region中的全部流程. NoSQL漫谈 本文整体思路 前文内容回顾 示例数据 HBase可选接口介绍 表服务接口介绍 介绍几种写数据的模式 如何构建Put对象(包含RowKey定义以及列定义) 数据路由 Client侧的分组打包 Client发RPC请求到Regi

处理分页 当前页&gt;1时, 操作的最后一页的最后一条数据后,向前提前一页

* handleAgentJobs({ payload }, { call, put }) { const data = yield call(handleAgentJob, payload) if (data && data.code === 200) { yield put({ type: 'handleAgentAbandonPage', payload }); } else { message.error(data && data.message || '请求失败'