Python 带outerjoin的查询(模型)sqlalchemy具有隐式的distinct?

Python 带outerjoin的查询(模型)sqlalchemy具有隐式的distinct?,python,sqlalchemy,flask-sqlalchemy,Python,Sqlalchemy,Flask Sqlalchemy,考虑以下模型: class Order(db.Model): id = db.Column(db.Integer, primary_key=True) status = db.Column(db.Enum('Ordered', 'Delivered'), default='Ordered', nullable=False) skus = db.relationship('SKU', order_by='SKU.index', back_populates='order',

考虑以下模型:

class Order(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    status = db.Column(db.Enum('Ordered', 'Delivered'), default='Ordered', nullable=False)
    skus = db.relationship('SKU', order_by='SKU.index', back_populates='order', passive_deletes=True)

class SKU(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    order_id = db.Column(db.Integer, db.ForeignKey('order.id', onupdate='CASCADE', ondelete='CASCADE'), nullable=False)
    order = db.relationship('Order', lazy='joined', back_populates='skus', innerjoin=True)

    index = db.Column(db.Integer)

    supplier = db.Column(db.Integer)
db
对象是
SQLAlchemy
中的
SQLAlchemy
的实例)

测试数据为三个SKU,按单个顺序排列:

+----+---------+
| id | status  |
+----+---------+
| 10 | Ordered |
+----+---------+
+----+----------+-------+----------+
| id | order_id | index | supplier |
+----+----------+-------+----------+
| 28 |       10 |     0 |       10 |
| 29 |       10 |     1 |       10 |
| 30 |       10 |     2 |       10 |
+----+----------+-------+----------+
有人会认为,对
SKU
使用显式外部联接
Order
将产生笛卡尔积并返回3行,这是不正确的。这将打印单个“已订购”:

尽管如此,还是生成了正确的查询(并按预期返回3行):

我猜SQLAlchemy会以某种方式检测重复的Order对象并将其从最终列表中删除。但这有记录吗?这背后的原因是什么

同时,查询状态字段没有这个问题:3行打印在这里:

statuses = (db.session.query(Order.status).outerjoin(SKU)
              .filter(SKU.supplier == 10).all())
for (status, ) in statuses:
     print status

如果只是查询一个实体,并且您只是请求订单实体,那么重复的实体将根据标识/主键被剔除,这是正确的。例如,与带有实体(订单,SKU)的订单.query.outerjoin(SKU)…进行比较。。记不清是否记录了这些信息,但将尝试查找这些信息。理由可能是,由于返回的实体无论如何都是标识映射的,因此具有重复项的列表只包含对同一对象的多个引用,如果只是查询实体,返回此类重复项是没有意义的。@IljaEverilä,是的,你说得对。用实体(订单、SKU)添加
并用
替换订单中(订单、SKU)的循环:
解决了问题(至少对于测试用例)。不过,我将坚持显式字段查询。
SELECT `order`.id AS order_id, `order`.status AS order_status 
FROM `order` LEFT OUTER JOIN `SKU` ON `order`.id = `SKU`.order_id 
WHERE `SKU`.supplier = %(supplier_1)s
statuses = (db.session.query(Order.status).outerjoin(SKU)
              .filter(SKU.supplier == 10).all())
for (status, ) in statuses:
     print status