python - SQL炼金术 | 将连接结果限制为一行以实现一对多关系
问题描述
我有两个实体:项目和学生名单。一个项目可以有多个学生列表。
我正在尝试加入项目的学生列表,并且仅根据学生列表的自定义顺序返回每个项目的第一行。
尝试的子查询:
_whens = {ProjectStatus.APPROVED: 1, ProjectStatus.REJECTED: 2,
ProjectStatus.SUBMITTED: 3, None: 4}
sort_order = case(value=StudentList.student_list_status_id, whens=_whens)
return self._session.query(StudentList).
filter(StudentList.student_list_id==Project.project_id)
.order_by(sort_order).limit(1).subquery()
上面我定义了基于学生列表状态 ID 的自定义排序。该函数返回子查询,然后我尝试加入下面的项目外部查询(student_list_subquery 指的是上面返回的内容):
projects = self._session.query(models.Project)
.filter(models.Project.project_year == year)
.join(student_list_subquery,
student_list_subquery.c.project_id==Project.project_id)
.all()
下面是相关的 SQL 输出
FROM project
LEFT OUTER JOIN (SELECT student_list.project_id AS project_id,
student_list.student_list_id AS student_list_id
FROM student_list, project
WHERE project.project_id = student_list.project_id
ORDER BY CASE student_list.student_list_status_id WHEN 102 THEN 1
WHEN 105 THEN 2 WHEN 101 THEN 3 WHEN NULL THEN 4 END
LIMIT 1) AS anon_1 ON anon_1.project_id = project.project_id
我正在使用 mySQL,因此(Distinct On)解决方案将不起作用,row_number/partition 解决方案也不会......
我似乎在这里提出了同样的问题SQLAlchemy: FROM entry still present in associated subquery
解决方案
我有类似的问题。解决方案是使用 LATERAL sqlalchemy 方法:
subquery = select([student_list.c.project_id, student_list.c.student_list_id])\
.where(student_list.c.project_id == project.project_id)\
.limit(1)\
.lateral('students')
query = select([project.c.project_name, subquery.c.project_id, subquery.c.student_list_id])\
.select_from(project.join(subquery))
推荐阅读
- javascript - 弹出模型未在 for 循环中打开 (HTML)
- javascript - 为什么异步等待返回一个承诺?
- python - 使用 BeautifulSoup 抓取 React 页面
- arrays - 如何计算 Swift 中两个元素的出现次数?
- reactjs - 电子中的 ENV。可能吗?
- android - Android NDK Build: ld: error: failed to write to the output file: Permission denied
- c# - 如何将非统一的 int 范围映射到 C# 中的某些字符串值?
- javascript - 如何延迟验证 TextField?
- python-3.x - 如何识别变量是否在列表中?
- django - 如何在 Django 中创建动态模型和表单