SQLAlchemy多表左外连接结合group by查询报错解决
报错翻译
你遇到的报错原文中文含义如下:
sqlalchemy.exc.InvalidRequestError: 无法确定如何与映射器<Mapper at 0x7f88d80cd520; DisUser>建立连接。请使用
.select_from()方法明确指定连接的左表,若不存在可自动推导关联的外键配置,还需提供显式ON子句解决连接歧义。
问题根源
你最初的写法用的是默认内连接,只会返回Dis和DisUser同时匹配的记录,也就是有用户关联的Dis条目,无法返回全量Dis。后续尝试的左连接写法存在三个问题导致报错或结果不符合预期:
select_from同时传入Dis、DTypes两个表,SQLAlchemy无法判断左外连接要从哪个表出发关联DisUser,也没有显式指定连接条件- 把Dis和DisUser的关联条件写在
filter中,会强制把左外连接转为内连接,依旧会过滤掉没有用户关联的Dis记录 - 分组字段选了
DisUser.did,左连接后无关联用户的Dis记录对应的DisUser.did值为NULL,会被错误分到同一组,统计结果异常
正确可运行的写法
dis_data = db.session.query( Dis, DTypes, func.count(DisUser.did).label('dis_count') ).outerjoin( DisUser, Dis.id == DisUser.did # 显式指定左连接条件,左表为Dis ).join( DTypes, Dis.tid == DTypes.id # 若存在无分类的Dis需要保留,把此处join换成outerjoin即可 ).filter( DTypes.id == dtype ).group_by( Dis.id, DTypes.id # 按主键分组,兼容ONLY_FULL_GROUP_BY模式 ).all()
关键修改说明
- 去掉了查询字段中冗余的
DisUser.did,无关联用户时该字段为NULL,直接通过Dis对象的id属性即可获取主键值 - 左连接DisUser时显式声明关联条件,明确左表为Dis,直接解决连接歧义报错
- 关联条件放在
outerjoin的ON子句中而非filter里,保证左连接特性生效,返回全部Dis条目 - 分组字段改为Dis、DTypes的主键,既兼容数据库的全组模式校验,也能保证无关联用户的Dis条目计数为0,符合统计预期
内容的提问来源于stack exchange,提问作者Ahmad
相关产品推荐
相关产品推荐

