https://www.52ecy.cn/post-105.html
1、场景:查询一个选手的排名及距离上一名差多少票
方法一(定义变量累加排序)
\$temp = DB::fetch_all("SELECT a.cid,a.total,a.forge_vote,a.jewel_vote,(@rowNum:=@rowNum+1) AS rank FROM pre_vote_competition AS a, (SELECT (@rowNum :=0) ) b WHERE aid={\$aid} ORDER BY (a.total+a.forge_vote+a.jewel_vote) DESC ");
foreach (\$temp as \$key => \$value) {
if (\$value['cid'] == \$cid) {
//当前自己的排名
\$rank = \$value['rank'];
if (\$up) {
\$up = \$up - (\$value['total'] + \$value['forge_vote'] + \$value['jewel_vote']);
}
break;
}
//和上一名选手相差的票数
\$up = \$value['total'] + \$value['forge_vote'] + \$value['jewel_vote'];
}
2、场景:查询一篇文章的上一篇和下一篇,支持断号
\$sql = "
SELECT
*
FROM
" . DB::table(\$this->_table) . "
WHERE
aid IN (
SELECT
CASE
WHEN SIGN(aid - {\$id}) > 0 THEN MIN(aid)
WHEN SIGN(aid - {\$id}) < 0 THEN MAX(aid)
END AS aid
FROM
pre_exe_article
WHERE
aid <> {\$id}
GROUP BY
SIGN(aid - {\$id})
ORDER BY
SIGN(aid - {\$id})
)
ORDER BY
aid ASC";
return DB::fetch_all(\$sql);
方法二(去重排序查询比自己少的数量)
\$temp = DB::fetch_first("SELECT distinct total+jewel_vote+forge_vote ,COUNT(*)+1 AS RANK FROM " . DB::table('vote_competition') ." WHERE total+jewel_vote+forge_vote>" . \$competition['all'] . " and aid={\$aid} ORDER by forge_vote desc");
\$rank = \$temp['RANK'];
//无法直接查询到上一名选手票数
if (\$temp['total+jewel_vote+forge_vote']) {
//这里查询出来的是和第一名选手相差的票数
\$up = \$temp['total+jewel_vote+forge_vote']-\$competition['all'];
}
3、批量更新MySQL多条记录的多个字段
mysql更新语句很简单,更新一条数据的某个字段,一般这样写:
UPDATE mytable SET myfield = 'value' WHERE id = '1';
如果更新同一字段为同一个值,mysql也很简单,修改下where即可:
UPDATE mytable SET myfield = 'value' WHERE id in (1,2,3);
那如果更新多条数据为不同的值,可能很多人会这样写:
foreach (\$display\_order as \$id => \$ordinal) {
\$sql = "UPDATE categories SET display\_order = \$ordinal WHERE id = \$id";
mysql\_query(\$sql);
}
即是循环一条一条的更新记录。
一条记录update一次,这样性能很差,也很容易造成阻塞。
那么能不能一条sql语句实现批量更新呢?
mysql并没有提供直接的方法来实现批量更新,但是可以用点小技巧来实现。
UPDATE mytable SET
myfield = CASE id
WHEN 1 THEN '3'
WHEN 2 THEN '4'
WHEN 3 THEN '5'
END
WHERE id IN (1,2,3)
这句sql的意思是,更新display\_order 字段:
如果id=1 则display\_order 的值为3,
如果id=2 则 display\_order 的值为4,
如果id=3 则 display\_order 的值为5。
即是将条件语句写在了一起。
这里的where部分不影响代码的执行,但是会提高sql执行的效率。
确保sql语句仅执行需要修改的行数,这里只有3条数据进行更新,而where子句确保只有3行数据执行。
更新多值
UPDATE categories SET
display\_order = CASE id
WHEN 1 THEN 3
WHEN 2 THEN 4
WHEN 3 THEN 5
END,
title = CASE id
WHEN 1 THEN 'New Title 1'
WHEN 2 THEN 'New Title 2'
WHEN 3 THEN 'New Title 3'
END
WHERE id IN (1,2,3)
封装成PHP函数,传入相应数据,一键生成sql
/\*\*
\* 批量更新函数
\* @param \$data array 待更新的数据,二维数组格式
\* @param array \$params array 值相同的条件,键值对应的一维数组
\* @param string \$table array 表
\* @param string \$field string 值不同的条件,默认为id
\* @return bool|string
\*/
function batchUpdate(\$data, \$field, \$table ,\$params = [])
{
if (!is\_array(\$data) || !\$field || !\$table || !is\_array(\$params)) {
return false;
}
\$updates = parseUpdate(\$data, \$field);
\$where = parseParams(\$params);
// 获取所有键名为\$field列的值,值两边加上单引号,保存在\$fields数组中
// array\_column()函数需要PHP5.5.0+,如果小于这个版本,可以自己实现,
// 参考地址:[http://php.net/manual/zh/function.array-column.php#118831](http://php.net/manual/zh/function.array-column.php#118831)
\$fields = array\_column(\$data, \$field);
\$fields = implode(',', array\_map(function(\$value) {
return "'".\$value."'";
}, \$fields));
\$sql = sprintf("UPDATE \`%s\` SET %s WHERE \`%s\` IN (%s) %s", \$table, \$updates, \$field, \$fields, \$where);
return \$sql;
}
/\*\*
\* 将二维数组转换成CASE WHEN THEN的批量更新条件
\* @param \$data array 二维数组
\* @param \$field string 列名
\* @return string sql语句
\*/
function parseUpdate(\$data, \$field)
{
\$sql = '';
\$keys = array\_keys(current(\$data));
foreach (\$keys as \$column) {
\$sql .= sprintf("\`%s\` = CASE \`%s\` \\n", \$column, \$field);
foreach (\$data as \$line) {
\$sql .= sprintf("WHEN '%s' THEN '%s' \\n", \$line[\$field], \$line[\$column]);
}
\$sql .= "END,";
}
return rtrim(\$sql, ',');
}
/\*\*
\* 解析where条件
\* @param \$params
\* @return array|string
\*/
function parseParams(\$params)
{
\$where = [];
foreach (\$params as \$key => \$value) {
\$where[] = sprintf("\`%s\` = '%s'", \$key, \$value);
}
return \$where ? ' AND ' . implode(' AND ', \$where) : '';
}
批量替换字符串
UPDATE \`emlog\_blog\` SET \`content\` = replace (\`content\`,'ws2.sinaimg.cn','cdn.sinaimg.cn.52ecy.cn') WHERE \`content\` LIKE '%ws2.sinaimg.cn%'