当使用多个子查询和其中一个子查询内部的连接时,似乎sqlalchemy的count()函数没有返回与python的len()函数相同的值。问题是,我一般都在做子查询错误,或者sqlalchemy中是否有错误或者这里发生了什么?在这种情况下,可以用SQL如何处理计数来解释这种行为吗?
以下完全正常的小型演示代码:
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Boolean
from sqlalchemy.orm import sessionmaker
# creating a DB in memory, is removed when program stops
engine = create_engine('sqlite:///:memory:', echo=True)
engine.connect()
Base = declarative_base()
# tables
class TableA(Base):
__tablename__ = 'table_a'
id = Column(Integer, primary_key=True)
name = Column(String)
foo = Column(Boolean)
class TableB(Base):
__tablename__ = 'table_B'
id = Column(Integer, primary_key=True)
id_table_a = Column(Integer)
bar = Column(Boolean)
# mapping
Base.metadata.create_all(engine)
# session
Session = sessionmaker(bind=engine)
s = Session()
# Test records
s.add(TableA(name='test_1', foo=True)) # relevant main
s.add(TableA(name='test_2', foo=True))
s.add(TableA(name='test_3', foo=False))
s.add(TableB(id_table_a=1, bar=False)) # relevant entry 1
s.add(TableB(id_table_a=1, bar=False)) # relevant entry 2
s.add(TableB(id_table_a=2, bar=True))
# sub queries
sub1 = s.query(TableA).filter(TableA.name == 'test_1').subquery()
sub2 = s.query(TableA).join(TableB, TableB.id_table_a == TableA.id).filter(TableB.bar == False).subquery()
sub_q = s.query(TableA).filter(
TableA.id == sub1.c.id,
TableA.id == sub2.c.id
)
sub_count = sub_q.count()
sub_all = sub_q.all()
print "unrelevant count all: " + str(s.query(TableA).count())
print "sql count: " + str(sub_count)
print "python len: " + str(len(sub_all))
print sub_all
print sub_all[0].name
代码打印这些值:
unrelevant count all: 3
sql count: 2
python len: 1
[<__main__.TableA object at 0x0330FC90>]
test_1
正如你所看到的,count()返回值2,但如果我接受all()然后使用pythons len()函数将返回1.如果我不加入tableB,则计数工作正常,但是当加入时,只需从TableB记录中获取计数,如果连接条件匹配(即id_table_a == 1和bar == False)。
至少Postgres和sqlite会出现同样的问题。