我们有两个表:用户和权限
我们想要选择所有没有“访客”权限的用户。现在,用户可以拥有多个权限(而不仅仅是 1 个),因此简单地查询 !"guest"是行不通的。这是我们的查询现在的样子:
query = session.query(Users).join(Permission, and_(
Permission.userId == theUser.uid, Permission.deviceId== theDevice.uid))
query.join(Permission).filter(~exists().where(and_(Permission.level==SqlConstants.PermissionLevels.GUEST, Users.uid == Permission.userId)))
我不确定第一行中的连接是否与我们遇到的问题相关,但我们正在使用它,所以我将其包含在这里。 (如果不相关,我会将其编辑掉。)
上面返回以下异常:
returned no FROM clauses due to auto-correlation; specify correlate(<tables>) to control correlation manually.
我从以下 SO 帖子中收集了这个模式: Using NOT EXISTS clause in sqlalchemy ORM query
以及来自 sqlalchemy 文档(关于不存在的内容很浅薄): http://docs.sqlalchemy.org/en/rel_1_0/orm/query.html
我不清楚我做错了什么或是否有更好的方法。
最佳答案
我不完全确定我已经理解你的问题,主要是因为我想出的解决方案非常简单。我会尝试一下,无论如何我希望它能对您有所帮助。
我能够轻松地重现使用 exists
时遇到的异常。我认为发生这种情况是因为在 where
参数中,您混合了 join
中两个表中的列。如果你或多或少像这样重写它,它不会给出异常,
sq = session.query(Users.pk).join(Permission).filter(Permission.level==SqlConstants.PermissionLevels.GUEST)
q = session.query(Users).join(Permission).filter(~sq.exists())
但是它不起作用,因为一旦 Permission
中存在 1 个具有 GUEST 级别的寄存器,查询将根本不会给出任何结果。
但是为什么不这样重写呢?
sq = session.query(Users.pk).join(Permission).filter(Permission.level==SqlConstants.PermissionLevels.GUEST)
q = session.query(Users).filter(~Users.pk.in_(sq))
在我的试验中,如果我正确理解了你的问题,它就会起作用。
仅供引用,这是我使用的玩具示例,其中表 A
对应于 Users
,B
对应于 Permission
> 和 B.attr
将存储权限级别。
In [2]:
class A(Base):
__tablename__ = 'A'
pk = Column('pk', Integer, primary_key=True)
name = Column('name', String)
class B(Base):
__tablename__ = 'B'
pk = Column('pk', Integer, primary_key=True)
fk = Column('fk', Integer, ForeignKey('A.pk'))
attr = Column('attr', Integer)
a = relationship("A", backref='B')
这是我插入的数据,
In [4]:
q = session.query(B)
print(q)
for x in q.all():
print(x.pk, x.fk, x.attr)
q = session.query(A)
print(q)
for x in q.all():
print(x.pk, x.name)
SELECT "B".pk AS "B_pk", "B".fk AS "B_fk", "B".attr AS "B_attr"
FROM "B"
1 1 1
2 1 2
3 2 0
4 2 4
5 1 4
SELECT "A".pk AS "A_pk", "A".name AS "A_name"
FROM "A"
1 one
2 two
3 three
这是查询的结果,
In [16]:
from sqlalchemy import exists, and_, tuple_
sq = session.query(A.pk).join(B).filter(B.attr==2)
print(sq)
q = session.query(A).filter(~A.pk.in_(sq))
print(q)
for x in q.all():
print(x.pk, x.name)
SELECT "A".pk AS "A_pk"
FROM "A" JOIN "B" ON "A".pk = "B".fk
WHERE "B".attr = :attr_1
SELECT "A".pk AS "A_pk", "A".name AS "A_name"
FROM "A"
WHERE "A".pk NOT IN (SELECT "A".pk AS "A_pk"
FROM "A" JOIN "B" ON "A".pk = "B".fk
WHERE "B".attr = :attr_1)
2 two
3 three
希望对你有帮助!
关于python - Sqlalchemy使用orm选择所有连接不存在的mysql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32658805/