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

如何在SQLAlchemy中查询关联模型无指定属性的模型

获取无指定关联模型的目标模型(Flask-SQLAlchemy/SQLAlchemy方案)

嘿,我来帮你搞定这个查询问题!首先得先补全下关联表的合理定义(你提到移除了无关字段,所以默认ReportKPI是KPI和Report的多对多关联表,完整的模型应该是这样才说得通):

class ReportKPI(db.Model):
    __tablename__ = 'report_kpis'
    report_id = db.Column(db.Integer, db.ForeignKey('reports.id'), primary_key=True)
    kpi_id = db.Column(db.Integer, db.ForeignKey('kpis.id'), primary_key=True)

假设你的核心需求是:获取所有没有关联到identifier为某个特定值(比如"target_kpi")的KPI的Report实例,或者更通用的——获取不存在满足某条件的关联模型的目标模型,这里以Report为目标、关联的KPI有指定属性为例,给你几种实用的方案:

方案1:使用NOT EXISTS子查询(推荐,性能友好)

这是最直观、通常性能也最好的写法,直接检查当前Report是否不存在符合条件的关联KPI:

target_identifier = "specific_kpi"

# Flask-SQLAlchemy 写法
reports = db.session.query(Report).filter(
    ~db.exists().where(
        db.and_(
            ReportKPI.report_id == Report.id,
            ReportKPI.kpi_id == KPI.id,
            KPI.identifier == target_identifier
        )
    )
).all()

# 标准 SQLAlchemy 写法(核心逻辑一致,只是 session 调用方式不同)
from sqlalchemy import exists, and_
reports = session.query(Report).filter(
    ~exists().where(
        and_(
            ReportKPI.report_id == Report.id,
            ReportKPI.kpi_id == KPI.id,
            KPI.identifier == target_identifier
        )
    )
).all()

方案2:左连接+IS NULL检查

通过左连接关联到符合条件的KPI关联记录,然后筛选出没有匹配结果的Report:

target_identifier = "specific_kpi"

# Flask-SQLAlchemy 写法
reports = db.session.query(Report).outerjoin(
    ReportKPI,
    db.and_(
        Report.id == ReportKPI.report_id,
        ReportKPI.kpi_id == KPI.id,
        KPI.identifier == target_identifier
    )
).filter(ReportKPI.report_id.is_(None)).all()

# 标准 SQLAlchemy 写法
from sqlalchemy import and_
reports = session.query(Report).outerjoin(
    ReportKPI,
    and_(
        Report.id == ReportKPI.report_id,
        ReportKPI.kpi_id == KPI.id,
        KPI.identifier == target_identifier
    )
).filter(ReportKPI.report_id.is_(None)).all()

方案3:使用NOT IN子查询

如果需要的话,也可以先获取所有关联了指定KPI的Report ID,再取不在这个集合里的Report:

target_identifier = "specific_kpi"

# Flask-SQLAlchemy 写法
related_report_ids = db.session.query(ReportKPI.report_id).join(
    KPI, ReportKPI.kpi_id == KPI.id
).filter(KPI.identifier == target_identifier).subquery()

reports = db.session.query(Report).filter(
    Report.id.notin_(related_report_ids)
).all()

# 标准 SQLAlchemy 写法
related_report_ids = session.query(ReportKPI.report_id).join(
    KPI, ReportKPI.kpi_id == KPI.id
).filter(KPI.identifier == target_identifier).subquery()

reports = session.query(Report).filter(
    Report.id.notin_(related_report_ids)
).all()

额外补充

  • 如果你的需求是获取完全没有关联任何KPI的Report(不管KPI的属性),只需要去掉KPI.identifier == target_identifier这个条件就行。比如方案1里只保留ReportKPI.report_id == Report.id和ReportKPI.kpi_id == KPI.id,或者更简单直接关联ReportKPI。
  • 要是你已经在模型里定义了关系(比如Report.kpis = db.relationship('KPI', secondary='report_kpis', backref='reports')),写法还能更简洁:
# 已定义模型关系的情况下
reports = db.session.query(Report).filter(
    ~Report.kpis.any(KPI.identifier == target_identifier)
).all()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:26:15