python - Sqlalchemy使用orm选择所有连接不存在的mysql

标签 python mysql sqlalchemy not-exists

我们有两个表:用户和权限

我们想要选择所有没有“访客”权限的用户。现在,用户可以拥有多个权限(而不仅仅是 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 对应于 UsersB 对应于 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/

相关文章:

python - Pydub - 将 split_on_silence 与最小长度/文件大小相结合

python - 正则表达式 - 查找包含至少 1 个大写字母、一位数字或一个特殊字符的连续 'words'

python - VersionOne.SDK.Python 创建故事时出现异常

python - 如何在matplotlib散点图中绘制相关线?

php - 如何将变量数据存储到我的数据库中

mysql - 使用 4 个 JOINS 和优化 MySQL 查询

html - SQL 查询未显示正确的结果

python - 将 SQLAlchemy 与多个自引用外键一起使用

python - 在 sqlalchemy 中使用计算列更新表

python - 如何使用 SQLAlchemy 创建一个新数据库?