python - SQL炼金术 |对于一对多关系,将连接结果限制为一行

标签 python mysql sqlalchemy flask-sqlalchemy

我有两个实体:项目和学生名单。 一个项目可以有多个学生名单。

我正在尝试加入项目的学生列表,并且仅根据学生列表的自定义排序返回每个项目的第一行。

尝试的子查询:

_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 correlated subquery

最佳答案

终于解决了这个问题。希望这有助于其他人在使用 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 函数的结果。

关于python - SQL炼金术 |对于一对多关系,将连接结果限制为一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50109243/

相关文章:

python - 同时使用 Conda、PIP 和 Jupyter Notebook 的路径困惑

python - SQLAlchemy 与 PostgreSQL 和全文搜索

python - 从同一文件夹中的文件导入功能

python - 保留满足条件的行和相邻行

mysql - 如何完全删除 mariaDB 以便我可以重置 root 密码?

mysql - 检查 field = '' 与 field IS NULL 是否有任何速度差异?

python - SQLalchemy "load_only"不只加载指定的列

python - 查询 SQL Server 数据库时结果对象不返回行

python - 如何在 PyMongo 中索引已知字段的未知字段?

php - 对于非常小的数字,删除数字格式中的 "E"