order高级排序
可以使用order方法结合case语句进行条件排序。以下示例展示了如何按照销量和上架时间进行动态排序:
use think\facade\Db;
Db::name('goods')
->orderRaw("case when sales >= 1000 then 0 else 1 end, putaway_time desc")
->select();
在上面的示例中,orderRaw方法使用了原生的SQL表达式,其中包含了case语句。case语句的作用是根据销量进行分类,如果销量超过了1000,则分类为0,否则分类为1。然后按照分类结果进行排序,分类结果相同的再按照上架时间从晚到早排序。
另外,也可以使用orderCase方法对多个字段进行动态排序。例如,以下示例展示了如何按照商品价格和销量进行动态排序:
use think\facade\Db;
Db::name('goods')
->orderCase([
'(price < 50)' => '2', // 如果价格小于50,优先级最高,分类值为2
'(sales > 1000)' => '1', // 如果销量大于1000,优先级次之,分类值为1
'1=1' => '0', // 如果都不符合,优先级最低,分类值为0
], [
'price' => 'asc', // 按照价格从低到高排序
'sales' => 'desc', // 如果价格相同,则按照销量从高到低排序
])
->select();
在上面的示例中,orderCase方法的第一个参数是一个关联数组,键名是要进行分类的表达式,键值是分类值。如果要同时对多个条件进行判断,可以使用括号将条件括起来,并用逻辑运算符连接。分类值越大,优先级越高。第二个参数和之前的示例一样,表示按照价格和销量进行排序。
需要注意的是,在使用orderRaw或orderCase方法时,要注意安全性问题,避免SQL注入攻击。可以使用Db::raw方法将原生的SQL表达式转义为字符串。
实际使用案例:
//列表检索
public function get_list($param = [], $where = [], $whereOr=[])
{
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
$now = time();
$nowa = $now+2678400;
$list = self::where($where)
->where(function ($query) use($whereOr) {
if (!empty($whereOr)){
$query->whereOr($whereOr);
}
})
->field('a.*, d.title as sign_department,cu.name as customer')
->alias('a')
->join('department d', 'a.sign_did = d.id','LEFT')
->join('customer cu', 'a.customer_id = cu.id','LEFT')
->orderRaw("
CASE
WHEN a.check_status = 0 THEN 1 -- 未提交
WHEN a.check_status = 1 THEN 2 -- 审核中
WHEN a.end_time < {$now} AND a.end_time>0 AND history_time = 0 THEN 3 -- 到期(基于end_time和history_time判断)
WHEN a.end_time > {$now} AND a.end_time < {$nowa} AND a.end_time>0 AND history_time = 0 THEN 4 -- 到期(基于end_time和history_time判断)
ELSE 5 -- 其他(如果有其他状态或不符合上述条件的记录)
END ASC
")
->paginate($rows, false, ['query' => $param])
->each(function ($item, $key) {
$item->sign_time = date('Y-m-d', $item->sign_time);
});
return $list;
}