【问题标题】:SQL List items that appears less than N times in another tableSQL 列出在另一个表中出现少于 N 次的项目
【发布时间】:2023-03-12 10:18:01
【问题描述】:

这是我的数据库模型。

class Doctor(db.Model):
    __tablename__ = 'doctor'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), nullable=False)

class Patient(db.Model):
    __tablename__ = 'patient'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(120), nullable=False)

class Assignment(db.Model):
    __tablename__ = 'assignment'
    doctorid = db.Column(db.Integer, ForeignKey('doctor.id'),
                        unique=False, nullable=False, index=True, primary_key=True)
    patientid = db.Column(db.Integer, ForeignKey('patient.id'),
                       unique=False, nullable=False, index=True, primary_key=True)
    created = db.Column(db.DateTime(timezone=False),
                        server_default=db.func.now())

我想列出分配了少于 3 名(可能是用户指定的N)患者的所有医生。 分配使用 ForeignKey 记录在 assignment 表中。

请注意,有些医生可能为零 分配的患者,他们也应该包含在结果中。

我在考虑诸如子查询、GROUP BY 或 OUTER JOIN 之类的东西,但我不知道如何将计数 N 放入其中。

另外,我想从结果中进一步排除分配给某个患者patientid = P1 的所有医生。除了第一个(小于N)条件之外,是否可以这样做?

【问题讨论】:

    标签: python sql sqlalchemy


    【解决方案1】:

    要计算每个医生的分配数量,请使用 GROUP BY 并仅选择组,在这种情况下,满足特定条件的医生使用 HAVING 子句。如果它们在功能上依赖于分组,则可以从组中确定性地选择非聚合列,如果按主键分组就是这种情况。

    docs = db.session.query(Doctor).\
        outerjoin(Assignment).\
        group_by(Doctor.id).\
        having(
            db.func.count(Assignment.patientid) < n,
            db.func.count().filter(Assignment.patientid == p1) == 0).\
        all()
    

    如果您的 DBMS 不支持上述用于消除分配给患者 P1 的医生的聚合 FILTER 子句,则可以使用 SQL 标准布尔聚合函数 any() / some() 代替(如果支持)(PostgreSQL 中的 bool_or()):

    # PostgreSQL only
    ...having(..., db.not_(db.func.bool_or(Assignment.patientid == p1)))
    

    或使用 EXISTS 子查询表达式代替:

    docs = db.session.query(Doctor).\
        outerjoin(Assignment).\
        filter(db.not_(db.session.query(Assignment).filter(
            Assignment.patientid == p1,
            Assignment.doctorid == Doctor.id).exists())).\
        group_by(Doctor.id).\
        having(db.func.count(Assignment.patientid) < n).\
        all()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-23
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多