You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中使用SqlDelight关联两张表的更优实现方案咨询

在SqlDelight中处理关联查询并实现嵌套数据结构的最优方式

在SqlDelight里,你可以通过**自定义映射器(mapper)**来实现主表数据嵌套子表列表的需求,不用再手动处理可空字段的繁琐判断。具体方案如下:

1. 拆分查询逻辑(避免N+1可选)

先分别定义主表和子表的查询语句:

  • 主表查询获取Sales部门的员工:
getSalesEmployees:
SELECT empId, name FROM EMPLOYEE WHERE dept = 'Sales';
  • 子表查询获取指定员工的课程:
getCoursesByEmpId:
SELECT courseId, courseName FROM COURSE WHERE empId = ?;

2. 定义目标嵌套数据类

先创建你期望的嵌套结构数据类(以Kotlin为例):

data class EmployeeWithCourses(
    val empId: String,
    val name: String,
    val courses: List<Course>
)

data class Course(
    val courseId: String,
    val courseName: String
)

3. 映射查询结果为嵌套结构

在代码层关联查询结果并组装:

fun getEmployeesWithCourses(): List<EmployeeWithCourses> {
    val employees = database.getSalesEmployees().executeAsList()
    return employees.map { emp ->
        val courses = database.getCoursesByEmpId(emp.empId).executeAsList()
            .map { Course(it.courseId, it.courseName) }
        EmployeeWithCourses(emp.empId, emp.name, courses)
    }
}

进阶:单次查询后分组(减少数据库交互)

如果不想执行N+1次查询,可通过一次JOIN获取所有数据,再在内存中分组处理:

定义JOIN查询

getSalesEmployeesWithCourses:
SELECT e.empId, e.name, c.courseId, c.courseName
FROM EMPLOYEE e
LEFT JOIN COURSE c ON e.empId = c.empId
WHERE e.dept = 'Sales';

内存分组映射

fun getEmployeesWithCourses(): List<EmployeeWithCourses> {
    val rawResults = database.getSalesEmployeesWithCourses().executeAsList()
    return rawResults.groupBy { it.empId }
        .map { (empId, group) ->
            val baseEmp = group.first()
            val courses = group.filter { it.courseId != null }
                .map { Course(it.courseId!!, it.courseName!!) }
            EmployeeWithCourses(empId, baseEmp.name, courses)
        }
}

两种方案都能避免手动处理大量可空字段,实现你需要的嵌套列表结构,可根据业务场景选择:拆分查询更直观,单次查询分组则减少数据库交互次数。

内容的提问来源于stack exchange,提问作者mk_369

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 01:00:03