我正在使用 SQLAlchemy 和 Python 处理查询一些 MySQL,问题是当我尝试在普通 SQL 管理工具中执行查询时(在我的例子中是
Navicat
),它工作得很好(只有 49k 条记录,并且没有按我想要的条件分组后有任何重复值)
select q1.*, cr.psubject_code, fs.num_of_credit as NOC, sum(cr.grade * fs.num_of_credit) as total_grade, sum(fs.num_of_credit) as total_NOC, sum(cr.grade * fs.num_of_credit)/sum(fs.num_of_credit) as average_grade
from
(select fg.id as group_id, fg.pterm_id as term_id, fg.pterm_name as term_name, fg.psubject_name as subject_name,
fgm.member_login
from fu_group fg
join fu_group_member fgm on fg.id = fgm.groupid
where fg.pterm_id >= 24 and fg.is_virtual = 0) q1 JOIN t7_course_result cr on (cr.groupid = q1.group_id and q1.member_login = cr.student_login) join fu_subject fs on cr.psubject_code = fs.subject_code
where cr.val = 1
group by q1.member_login
但是当我转换为Python中的
SQLALchemy ORM
代码时,它将一直工作到where子句cr.val = 1
,并且在尝试按q1.member_login
分组时得到重复的值。我进行了测试,发现如果我按 id 进行分组,它在正常 SQL 中会得到相同的结果,但是当我按某些类型为 VARCHAR
的属性进行分组时,它不仅会按我输入的条件进行分组中,还要根据自身情况进行具体记录。
async def avg_grade(engine, partitioner, mod_number):
q1 = select(fu_group.id, fu_group.pterm_id, fu_group_member.member_login, fu_group.pterm_name)\
.join_from(fu_group_member, fu_group, fu_group.id == fu_group_member.groupid)\
.where(
fu_group.pterm_id >= 24,
fu_group.is_virtual == 0,
).subquery()
q = select(q1.c.id, q1.c.pterm_id, q1.c.member_login, q1.c.pterm_name, t7_course_result.psubject_code,
func.sum(t7_course_result.grade * fu_subject.num_of_credit),
func.sum(fu_subject.num_of_credit),
cast(func.sum(t7_course_result.grade * fu_subject.num_of_credit)/func.sum(fu_subject.num_of_credit), DECIMAL(10, 1)),
)\
.join_from(q1, t7_course_result, and_(q1.c.id == t7_course_result.groupid,
q1.c.member_login == t7_course_result.student_login))\
.join_from(t7_course_result, fu_subject, t7_course_result.psubject_code == fu_subject.subject_code)\
.where(t7_course_result.val == 1, q1.c.id % 17 == mod_number)\
.group_by(q1.c.member_login)
这导致结果不仅仅是不同的member_login,它将重复
member_login
值,但具有我在 group_by()
子句中未提及的不同密钥。
有人能告诉我为什么会发生这种情况吗?这是
SQLAlchemy
的错误吗?
为
ORM
定义的类:
class fu_group(Base):
__tablename__= 'fu_group'
id = Column(BigInteger, primary_key=True)
pterm_id = Column(Integer, index=True)
pterm_name = Column(VARCHAR, index=True)
is_virtual = Column(SmallInteger, index=True)
psubject_name = Column(VARCHAR, index=True)
class fu_group_member(Base):
__tablename__ = 'fu_group_member'
id = Column(BigInteger, primary_key=True)
groupid = Column(BigInteger, index=True)
member_login = Column(VARCHAR, index=True)
class t7_course_result(Base):
__tablename__ = 't7_course_result'
id = Column(BigInteger, primary_key=True)
groupid = Column(BigInteger, index=True)
student_login = Column(VARCHAR, index=True)
val = Column(VARCHAR, index=True)
grade = Column(DECIMAL(10, 1), index=True)
psubject_code = Column(VARCHAR(25), index=True)
class fu_subject(Base):
__tablename__ = 'fu_subject'
id = Column(BigInteger, primary_key=True)
department_id = Column(Integer, index=True)
subject_code = Column(VARCHAR(25), index=True)
num_of_credit = Column(Integer, index=True)
不确定这影响多大!
看来您至少交换了此连接,您有
join_from(fu_group_member, fu_group)
但您原来的查询是 FROM fu_group fg JOIN fu_group_member
。我认为您希望 join_from(fu_group, fu_group_member, ...)
与之匹配。