本文目录导读:

在ThinkPHP中,子查询和闭包是处理复杂查询的两种重要方式,下面详细介绍它们的使用方法。
子查询
使用闭包构建子查询
// 基础子查询
$subQuery = Db::table('orders')
->field('user_id, SUM(amount) as total')
->group('user_id')
->buildSql();
$users = Db::table('users')
->alias('u')
->join($subQuery . ' o', 'u.id = o.user_id')
->select();
where中使用子查询
// IN子查询
$subQuery = Db::table('order')
->where('status', 1)
->field('user_id')
->buildSql();
$users = Db::name('user')
->where('id', 'IN', $subQuery)
->select();
// 使用闭包方式
$users = Db::name('user')
->where(function ($query) {
$query->where('id', 'IN', function ($query) {
$query->table('order')->where('status', 1)->field('user_id');
});
})
->select();
EXISTS子查询
// 使用闭包实现EXISTS
$users = Db::name('user')
->alias('u')
->whereExists(function ($query) {
$query->table('order')
->alias('o')
->where('o.user_id = u.id')
->where('o.amount', '>', 100);
})
->select();
// NOT EXISTS
$users = Db::name('user')
->alias('u')
->whereNotExists(function ($query) {
$query->table('order')
->alias('o')
->where('o.user_id = u.id');
})
->select();
闭包的高级用法
条件分组
// 复杂条件分组
$list = Db::name('user')
->where(function ($query) {
$query->where('status', 1)
->whereOr(function ($query) {
$query->where('score', '>', 80)
->where('level', '>=', 3);
});
})
->select();
动态条件构建
public function search($params)
{
$query = Db::name('user');
// 使用闭包动态添加条件
$query->where(function ($query) use ($params) {
// 关键词搜索
if (!empty($params['keyword'])) {
$query->where('name|email', 'like', "%{$params['keyword']}%");
}
// 状态筛选
if (isset($params['status'])) {
$query->where('status', $params['status']);
}
// 日期范围
if (!empty($params['start_date']) && !empty($params['end_date'])) {
$query->whereBetween('create_time', [
strtotime($params['start_date']),
strtotime($params['end_date'])
]);
}
});
return $query->paginate(15);
}
关联子查询
// 使用关联查询
$users = Db::name('user')
->alias('u')
->field('u.*, o.total_amount')
->join([
'SELECT user_id, SUM(amount) as total_amount FROM orders GROUP BY user_id' => 'o'
], 'o.user_id = u.id')
->select();
// 或者使用闭包
$users = Db::name('user')
->alias('u')
->join(function ($query) {
$query->table('orders')
->alias('o')
->where('o.user_id = u.id');
}, 'u.id = o.user_id')
->select();
实际应用示例
获取每个分类的最新商品
$sql = Db::table('products')
->field('id, category_id, name, price')
->order('create_time desc')
->buildSql();
$list = Db::table($sql . ' p')
->field('p.*')
->group('p.category_id')
->select();
用户消费排行
// 子查询获取用户消费总额
$subQuery = Db::table('orders')
->field('user_id, SUM(total_amount) as total_spent')
->where('status', 'paid')
->group('user_id')
->buildSql();
$rankList = Db::table('users')
->alias('u')
->join($subQuery . ' us', 'u.id = us.user_id')
->field('u.username, us.total_spent')
->order('us.total_spent desc')
->limit(10)
->select();
筛选有订单的用户
// 方式一:使用EXISTS
$users = Db::name('user')
->alias('u')
->whereExists(function ($query) {
$query->table('orders')
->where('user_id = u.id')
->where('status', 1);
})
->select();
// 方式二:使用IN
$users = Db::name('user')
->where('id', 'IN', function ($query) {
$query->table('orders')
->where('status', 1)
->field('user_id');
})
->select();
复杂报表统计
// 统计每个用户的订单和总金额
$list = Db::name('user')
->alias('u')
->field([
'u.id',
'u.username',
'COUNT(o.id)' => 'order_count',
'IFNULL(SUM(o.amount), 0)' => 'total_amount'
])
->join('orders o', 'o.user_id = u.id', 'LEFT')
->group('u.id')
->having('order_count > 0')
->select();
性能优化建议
使用buildSql避免重复查询
// 构建一次,多处使用
$subQuery = Db::name('orders')
->field('user_id, SUM(amount) as total')
->where('status', 1)
->group('user_id')
->buildSql();
// 多个查询中使用
$topUsers = Db::name('user')
->alias('u')
->join($subQuery . ' o', 'u.id = o.user_id')
->order('o.total desc')
->limit(10)
->select();
$userStats = Db::name('user')
->alias('u')
->join($subQuery . ' o', 'u.id = o.user_id')
->field('u.*, o.total')
->select();
使用索引优化
// 确保子查询的关联字段有索引
Db::name('user')
->where('id', 'IN', function ($query) {
$query->table('orders')
->where('status', 1)
->field('user_id');
})
->select();
// 注意:orders表的user_id和status字段应该建立复合索引
避免复杂嵌套
// 不推荐 - 过度嵌套
$result = Db::name('a')
->where('id', 'IN', function ($query) {
$query->table('b')
->where('cid', 'IN', function ($query) {
$query->table('c')->where('status', 1)->field('id');
})
->field('aid');
})
->select();
// 推荐 - 拆分为多个查询
$cids = Db::name('c')->where('status', 1)->column('id');
$aids = Db::name('b')->whereIn('cid', $cids)->column('aid');
$result = Db::name('a')->whereIn('id', $aids)->select();
子查询和闭包是处理复杂业务逻辑的重要工具,合理使用可以大大简化代码,但也要注意性能优化,避免过度复杂的嵌套查询。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播