mel*_*r55 3 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)))
Run Code Online (Sandbox Code Playgroud)
我不确定第一行中的连接是否与我们遇到的问题相关,但我们正在使用它,所以我将其包含在这里。(如果不相关的话我会编辑掉。)
上面返回以下异常:
returned no FROM clauses due to auto-correlation; specify correlate(<tables>) to control correlation manually.
Run Code Online (Sandbox Code Playgroud)
我从下面的SO帖子中收集了这个模式: Using NOT EXISTS Clause in sqlalchemy ORM query
以及来自 sqlalchemy 文档(关于不存在的内容很浅): http://docs.sqlalchemy.org/en/rel_1_0/orm/query.html
我不清楚我做错了什么或是否有更好的方法。
我不完全确定我已经理解你的问题,主要是因为我想出的解决方案非常简单。我会尝试一下,无论如何我希望它能以某种方式帮助你。
\n\n我能够轻松地重现使用时遇到的异常exists。我认为发生这种情况是因为在where参数中您混合了join. 如果你或多或少像这样重写它,它不会给出例外,
sq = session.query(Users.pk).join(Permission).filter(Permission.level==SqlConstants.PermissionLevels.GUEST)\nq = session.query(Users).join(Permission).filter(~sq.exists())\nRun Code Online (Sandbox Code Playgroud)\n\n然而它不起作用,因为一旦有 1 个PermissionGUEST 级别的寄存器,查询将根本不会给出任何结果。
但为什么不这样重写呢?
\n\nsq = session.query(Users.pk).join(Permission).filter(Permission.level==SqlConstants.PermissionLevels.GUEST)\nq = session.query(Users).filter(~Users.pk.in_(sq))\nRun Code Online (Sandbox Code Playgroud)\n\n在我的试验中,如果我正确理解了你的问题,它就会起作用。
\n\n仅供参考,这是我使用的玩具示例,其中 tableA对应于Users、Bto Permission,并且B.attr将存储权限级别。
In [2]:\n\nclass A(Base):\n __tablename__ = \'A\'\n\n pk = Column(\'pk\', Integer, primary_key=True)\n name = Column(\'name\', String)\n\n\nclass B(Base):\n __tablename__ = \'B\'\n\n pk = Column(\'pk\', Integer, primary_key=True)\n fk = Column(\'fk\', Integer, ForeignKey(\'A.pk\'))\n attr = Column(\'attr\', Integer)\n\n a = relationship("A", backref=\'B\')\nRun Code Online (Sandbox Code Playgroud)\n\n这是我插入的数据,
\n\nIn [4]:\n\nq = session.query(B)\nprint(q)\nfor x in q.all():\n print(x.pk, x.fk, x.attr)\n\nq = session.query(A)\nprint(q)\nfor x in q.all():\n print(x.pk, x.name)\n\xe2\x80\x8b\nSELECT "B".pk AS "B_pk", "B".fk AS "B_fk", "B".attr AS "B_attr" \nFROM "B"\n1 1 1\n2 1 2\n3 2 0\n4 2 4\n5 1 4\nSELECT "A".pk AS "A_pk", "A".name AS "A_name" \nFROM "A"\n1 one\n2 two\n3 three\nRun Code Online (Sandbox Code Playgroud)\n\n这是查询的结果,
\n\nIn [16]:\n\nfrom sqlalchemy import exists, and_, tuple_\nsq = session.query(A.pk).join(B).filter(B.attr==2)\nprint(sq)\nq = session.query(A).filter(~A.pk.in_(sq))\nprint(q)\n\xe2\x80\x8b\nfor x in q.all():\n print(x.pk, x.name)\nSELECT "A".pk AS "A_pk" \nFROM "A" JOIN "B" ON "A".pk = "B".fk \nWHERE "B".attr = :attr_1\nSELECT "A".pk AS "A_pk", "A".name AS "A_name" \nFROM "A" \nWHERE "A".pk NOT IN (SELECT "A".pk AS "A_pk" \nFROM "A" JOIN "B" ON "A".pk = "B".fk \nWHERE "B".attr = :attr_1)\n2 two\n3 three\nRun Code Online (Sandbox Code Playgroud)\n\n希望能帮助到你!
\n