首页 > 解决方案 > SQLAlchemy:选择一个表中不在另一个相关表中的所有记录

问题描述

我有两个表,ProjectData 和 Label,就像这样。

class ProjectData(db.Model):
    __tablename__ = "project_data"

    id = db.Column(db.Integer, primary_key=True)

class Label(db.Model):
    __tablename__ = "labels"

    id = db.Column(db.Integer, primary_key=True)
    data_id = db.Column(db.Integer, db.ForeignKey('project_data.id'))

我想要做的是从 ProjectData 中选择标签中未表示的所有记录 - 基本上与连接或右外连接相反,这不是 SQLAlchemy 提供的功能。

我试图这样做,但它不起作用。

db.session.query(ProjectData).select_from(Label).outerjoin(
        ProjectData
    ).all()

标签: pythondatabasesqlalchemyflask-sqlalchemy

解决方案


在一个表中查找但在另一个表中不匹配的记录称为反连接。

您可以通过NOT EXISTS查询来做到这一点:

    from sqlalchemy.sql import exists
    stmt = exists().where(Label.data_id == ProjectData.id)
    q = db.session.query(ProjectData).filter(~stmt)

生成此 SQL:

SELECT project_data.id AS project_data_id 
  FROM project_data 
  WHERE NOT (
    EXISTS (
      SELECT * 
      FROM labels 
      WHERE labels.data_id = project_data.id
    )
  )

或者通过LEFT JOIN对另一个表中的空 id 进行过滤:

q = (db.session.query(ProjectData)
               .outerjoin(Label, ProjectData.id == Label.data_id)
               .filter(Label.id == None)
    )

生成此 SQL:

SELECT project_data.id AS project_data_id 
  FROM project_data 
  LEFT OUTER JOIN labels ON project_data.id = labels.data_id  
  WHERE labels.id IS NULL

推荐阅读