实际项目中,遇到一个需求,需要先将所有数据库里的玩家进行排序,排序规则:每个分数段位选取前一百个玩家,放进排行榜数据表中,当遇到我们限定的分数上限值时,进行特殊处理,先选取大于上限值的一百个,叫做最强王者,然后在剩下的和等于上限值的当中,选取一百个,叫做至尊。
例子:比如分数是 1 3 5 8 13 15 40 69 那么选择1-3 3-5 5-8一直到40-69的一百个,直接插入排序表。对于大于69的分数,先选取一百个叫做最强王者段位,在选剩下的人和等于69的人中再选取一百个叫做至尊。至尊可能没有人。
解析:其实对于mysql语句很熟悉的人,可以写很多条mysql语句,放到.sql文件中,然后直接执行。但是我对于mysql并不是很熟悉,所以采用脚本相结合的方法。缺点很明显,mysql执行语句明显超多于正常使用mysql的语句。
#!/bin/bash
#从数据库找出各个段位,并根据经验值排序
./normal.sh #通用处理的脚本(最大值以下)
#./bb.sh
#开始插入排行榜数据库排名信息
./insert.sh
echo "success"
normal.sh
先将定义的ar数组确定,因为要处理69以及大于69的特殊规则,所以干脆直接多加两个位置70以及无限大10000
#!/bin/bash
rm -f a b
ar=(1 3 5 8 13 15 40 69 70 10000)
numone=0
numtwo=0
for i in ${ar[*]};do
if [ $numone -eq 0 ]
then
numone=$i
continue;
fi
numtwo=$i
mysql -uaaa -paaa -h***.***.***.*** tablename -e 'select CHARID from AUTOCHESSINFO where(TOTALEXP >= '$numone' && TOTALEXP < '$numtwo') order by TOTALEXP desc,CHARID;' > a
sed -i '1d' a
cat a >> b
echo "=$numtwo" >>b
numone=$i
done
insert.sh
这段shell脚本晦涩难懂,建议按照变量去看,而不是按照逻辑去看。每个变量的含义都很明确,看到他们的含义,就知道其实都是在为最强王者段位和至尊段位做特殊处理。
#!/bin/bash
(rm -f sepcial sepcialtwo)
rank=1
#每个段位人数
bigrank=100
num=1 #每个段位排名人数开始
flag=0 #顶部两个段位特殊处理
flagtwo=0 #王者段位
nosrot=0 #某一段位人数超过bigrank总限制 标志位
bigpos="=69" #至尊九段开始
bigpostwo="=70" #王者段位开始
while read -r line
do
if [[ $line == $bigpos ]] #判断王者段位
then
flag=1
nosrot=0
continue;
fi
if [ $nosrot -eq 1 ] #判断是否插入数据库
then
if [[ $line != *=* ]]
then
continue;
else
nosrot=0
fi
fi
if [ $flag -eq 1 ] #判断是否导入王者段位特殊处理文件
then
if [[ $line == $bigpostwo ]]
then
flagtwo=1 #王者段位
continue;
fi
if [ $flagtwo -eq 1 ]
then
echo $line >> sepcialtwo #王者段位特殊文件
else
echo $line >> sepcial #至尊九段特殊文件
fi
continue;
fi
if [[ $line != *=* ]] #普通段位正常插入处理
then
if [ $num -gt $bigrank ]
then
nosrot=1
continue;
fi
mysql -uaaa -paaa -h***.***.***.*** tablename -e 'insert into AUTOCHESSEXPRANK(RANKSEG,CHARID) values('$rank','$line');'
echo "insert into AUTOCHESSEXPRANK: rank:$rank,id:$line"
num=$(($num+1))
else
echo "$line"
num=1
rank=$(($rank+1))
tmp=$(($rank % 10))
if [ $tmp -eq 0 ]
then
rank=$(($rank+1))
fi
fi
done < b
sed -i '$d' sepcialtwo #删掉最后一行
echo "$bigpos"
ranktmp=$(($rank+1))
rank=0
#处理special
num=1
flagenough=0
while read -r line
do
if [ $num -gt $bigrank ] #特殊处理是否超限
then
if [ $flagenough -eq 1 ]
then
break;
fi
echo "$bigpostwo"
flagenough=1
num=1
rank=$ranktmp
fi
mysql -uaaa -paaa -h***.***.***.*** tablename -e 'insert into AUTOCHESSEXPRANK(RANKSEG,CHARID) values('$rank','$line');'
echo "insert into AUTOCHESSEXPRANK: rank:$rank,id:$line"
num=$(($num+1))
done < sepcialtwo
if [ $flagenough -eq 1 ]
then
if [ $num -le $bigrank ]
then
while read -r line
do
if [ $num -gt $bigrank ]
then
break;
fi
mysql -uaaa -paaa -h***.***.***.*** tablename -e 'insert into AUTOCHESSEXPRANK(RANKSEG,CHARID) values('$rank','$line');'
echo "insert into AUTOCHESSEXPRANK: rank:$rank,id:$line"
num=$(($num+1))
done < sepcial
fi
fi
这种方法确实能实现,但是缺点太过于明显。其实有更好的方法,就是每个段位执行一句sql,在处理最后的69和大于69的人的时候,先选取大于69的人一百个叫做最强王者,其次选取大于等于69的人但是不在最强王者段位表里的人,一百个叫做至尊。这样就ok,思想很明确,思路很清晰。