我有两个实体:项目和学生列表。 一个项目可以有许多学生列表。
我正在尝试加入项目的学生列表,并且只根据学生列表的自定义顺序返回每个项目的第一行。
尝试子查询:
_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定义自定义排序。该函数返回子查询,然后我尝试连接到我的Project外部查询(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 /分区解决方案也不会......
我似乎在这里提出了同样的问题SQLAlchemy: FROM entry still present in correlated subquery
答案 0 :(得分:1)
最后解决了这个问题。希望这可以帮助其他人在使用SQLAlchemy和mySQL进行自定义组排序时尝试解决第一组的问题。
首先我有这个函数返回一个具有项目最高优先级的student_list_status_id(因此是过滤器)。
@staticmethod
def create_student_list_subquery(session):
'''create a correlated subquery that will limit result to one student
list per project with custom sorting to retrieve highest priority list
per project based on status'''
sl2=aliased(StudentList)
list_id = sl2.student_list_status_id.label("list_id")
_whens = {ProjectStatus.APPROVED: 1, ProjectStatus.REJECTED: 2,
ProjectStatus.SUBMITTED: 3, None: 4}
sort_order = case(value=list_id, whens=_whens)
return session.query(list_id).filter(sl2.project_id==Project.project_id)
.order_by(sort_order)
.limit(1)
我加入项目状态,该状态与上面查询中的student_list_status_id(别名为ps)相关联到项目中。然后,我可以对项目状态名称进行排序,这是我的目标。
self._session.query(models.Project)
.filter(models.Project.project_year == year)
.join(ps, ps.project_status_id==student_list_subq)
.all()
请注意,student_list_subq是指上面create_student_list_subquery函数的结果。
答案 1 :(得分:0)
我遇到了类似的问题。 解决方案是使用 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))