假设表名为 user_courses
,字段为 user_id
和 course_name,存储每个用户选修的课程,想查询每个学生选修的所有课程
SQL 原生查询
SELECT user_id, GROUP_CONCAT(course_name) as courses FROM user_courses GROUP BY user_id;
ThinkPHP 代码实现
在 ThinkPHP 中,你可以使用查询构造器来实现类似的功能:
use think\facade\Db;
// 查询每个用户选修的所有课程
$data = Db::name('user_courses')
->field('user_id, GROUP_CONCAT(course_name) as courses') // 使用 GROUP_CONCAT 函数将课程合并
->group('user_id') // 按 user_id 分组
->select();
// 输出结果
print_r($data);
解释:
-
field('user_id, GROUP_CONCAT(course_name) as courses')
:选择user_id
和使用GROUP_CONCAT
函数将course_name
字段中该用户的所有课程组合成一个字符串,并命名为courses
。 -
group('user_id')
:按user_id
进行分组,确保每个用户只会有一行结果,并且课程会聚合到这一行中。
也可以使用模型查询
UserCourse.php
<?php
namespace app\model;
use think\Model;
class UserCourse extends Model
{
// 设置当前模型对应的完整数据表名称
protected $name = 'user_courses'; // 表名
}
use app\model\UserCourse;
$data = UserCourse::field('user_id, GROUP_CONCAT(course_name) as courses') // 聚合查询
->group('user_id') // 按用户分组
->select();
// 输出查询结果
print_r($data);
查询结果
返回的数据格式类似如下:
每个用户的 courses
字段是该用户选修的所有课程的组合,多个课程以逗号分隔。
[
['user_id' => 1, 'courses' => 'Math,English,History'],
['user_id' => 2, 'courses' => 'Physics,Chemistry'],
['user_id' => 3, 'courses' => 'Biology,Geography,Math']
]
扩展:
如果你想按字母顺序排列每个用户的课程,可以在 GROUP_CONCAT
中使用 ORDER BY
进行排序:
use think\facade\Db;
$data = Db::name('user_courses')
->field('user_id, GROUP_CONCAT(course_name ORDER BY course_name ASC) as courses')
->group('user_id')
->select();
print_r($data);
如果结果想以user_id为key
<?php
namespace app\controller;
use app\BaseController;
use app\model\UserCourse;
class Course extends BaseController
{
public function index()
{
// 查询每个用户选修的所有课程
$data = UserCourse::field('user_id, GROUP_CONCAT(course_name) as courses')
->group('user_id')
->select()
->toArray();
// 使用 array_column 将 user_id 作为键
$data = array_column($data, null, 'user_id');
// 返回 JSON 数据
return json($data);
}
}
结果
[
1 => ['user_id' => 1, 'courses' => 'Math,English,History'],
2 => ['user_id' => 2, 'courses' => 'Physics,Chemistry'],
3 => ['user_id' => 3, 'courses' => 'Biology,Geography,Math'],
]
如果想将字符串转为数组
// 将 courses 字段的字符串转换为数组
foreach ($data as &$item) {
$item['courses'] = explode(',', $item['courses']);
}
by 软件工程小施同学