SQL 列出在另一个 table 中出现少于 N 次的项目
SQL List items that appears less than N times in another table
这是我的数据库模型。
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
)患者的所有医生。
分配记录在 assignment
table using ForeignKey.
请注意,有些医生可能有零
患者分配,他们也应该包括在结果中。
我在考虑子查询、GROUP BY 或 OUTER JOIN 之类的东西,但我不知道如何将计数 N
放入其中。
此外,我想进一步从结果中排除分配给某个患者 patientid = P1
的所有医生。除了第一个(小于 N
)条件之外,还可以这样做吗?
要计算每个医生的分配数量,请使用 GROUP BY 并仅 select 组,在这种情况下,满足特定条件的医生使用 HAVING 子句。可以确定性地 select 来自组的非聚合列,如果它们在功能上依赖于分组,如果按主键分组就是这种情况。
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 不支持上面使用的聚合 FILTER 子句来消除分配给患者 P1 的医生,您可以改用 SQL 标准布尔聚合函数 any()
/ some()
如果支持(bool_or()
in PostgreSQL):
# 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()
这是我的数据库模型。
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
)患者的所有医生。
分配记录在 assignment
table using ForeignKey.
请注意,有些医生可能有零 患者分配,他们也应该包括在结果中。
我在考虑子查询、GROUP BY 或 OUTER JOIN 之类的东西,但我不知道如何将计数 N
放入其中。
此外,我想进一步从结果中排除分配给某个患者 patientid = P1
的所有医生。除了第一个(小于 N
)条件之外,还可以这样做吗?
要计算每个医生的分配数量,请使用 GROUP BY 并仅 select 组,在这种情况下,满足特定条件的医生使用 HAVING 子句。可以确定性地 select 来自组的非聚合列,如果它们在功能上依赖于分组,如果按主键分组就是这种情况。
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 不支持上面使用的聚合 FILTER 子句来消除分配给患者 P1 的医生,您可以改用 SQL 标准布尔聚合函数 any()
/ some()
如果支持(bool_or()
in PostgreSQL):
# 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()