【问题标题】:Use of label in sqlalchemy , database, ORM在 sqlalchemy、数据库、ORM 中使用标签
【发布时间】:2018-01-09 17:52:53
【问题描述】:
q = session.query(
    label('id1', func.least(Communication.initiator_id, Communication.receiver_id)),
    label('id2', func.greatest(Communication.initiator_id, Communication.receiver_id)),
    label('orga_id1', func.greatest(0, 1)),
    label('orga_id2', func.greatest(0, 1)),
    label('nb', func.count(Communication.id))
).filter(
    or_(
        Communication.initiator_id == people_id,
        Communication.receiver_id == people_id
    )
).order_by("nb").group_by('id1', 'id2').all()

所以我有这段代码,它工作正常,但我只想在这里添加一件事,那就是标签的使用。 例如,如何在我的其他标签中使用名称标签“id1”?

我的代码是这样的:

q = session.query(
    label('id1', func.least(Communication.initiator_id, Communication.receiver_id)),
    label('id2', func.greatest(Communication.initiator_id, Communication.receiver_id)),
    label('orga_id1', func.greatest(session.query(People).filter_by(id = "And here somehow i want the value that was created on first label with name 'id1'").first().orga_id, -1)),
    label('orga_id2', func.greatest(session.query(People).filter_by(id = "And here somehow i want the value that was created on second label with name 'id2'").first().orga_id, -1)),
    label('nb', func.count(Communication.id))
).filter(
    or_(
        Communication.initiator_id == people_id,
        Communication.receiver_id == people_id
    )
).order_by("nb").group_by('id1', 'id2').all()

有人可以解释一下我如何在查询中使用标签的值!!!

【问题讨论】:

  • 您不能以您尝试的方式从子查询中的父查询的选择列表中引用标签。另一方面,由于 SQLAlchemy 的auto correlation,您可以引用父表,因此您可以使用Communication.initiator_id 等。但是:Query.first() 会在那里执行查询。你想使用Query.as_scalar(),选择People.id
  • 但是例如,我可以在使用我的第一个示例结束查询后更改q[0].orga_id1 = "new value" 的值吗?如果是的话,我该怎么做? bcs 如果我喜欢q[0].orga_id1 = 11,我会收到错误can't set attribute
  • 我不确定我是否遵循。另一件事:如果您通过 id 过滤 People,首先选择然后使用它的 id,为什么还需要子查询呢?我的意思是session.query(People).filter_by(id=the_id1).first().id 将等于 id1。有错别字吗?
  • 已编辑,我正在搜索人们所在的组织 ID,bcs 我需要人员的 ID 以及他们正在工作的组织的 ID,但只能通过列中出现的 ID id1 id2 并有 2 列带有组织的 id

标签: python database python-3.x postgresql sqlalchemy


【解决方案1】:

您不能在子查询中引用父查询的输出列,但可以引用父查询的源表:

select 1 as one, (select one) as two;

不会起作用,但是

select 1 as one, (select s.i) as two from generate_series(2, 2) s(i);

确实如此。另一方面,您可以先执行查询以获取通信和计数,然后在顶部添加人员的组织 ID。按照您最初设想的方式使用标量子查询:

id1 = func.least(Communication.initiator_id, Communication.receiver_id)
id2 = func.greatest(Communication.initiator_id, Communication.receiver_id)

sq = session.query(id1.label('id1'),
                   id2.label('id2'),
                   func.count(Communication.id).label('nb')).\
    filter(or_(Communication.initiator_id == people_id,
               Communication.receiver_id == people_id)).\
    order_by('nb').\
    group_by('id1', 'id2').\
    subquery()

orga_id1 = session.query(People.orga_id).filter_by(id=sq.c.id1).as_scalar()
orga_id2 = session.query(People.orga_id).filter_by(id=sq.c.id2).as_scalar()

q = session.query(sq.c.id1,
                  sq.c.id2,
                  func.greatest(orga_id1, -1).label('orga_id1'),
                  func.greatest(orga_id2, -1).label('orga_id2'),
                  sq.c.nb).\
    all()

使用 LEFT JOIN:

from sqlalchemy.orm import aliased

id1 = func.least(Communication.initiator_id, Communication.receiver_id)
id2 = func.greatest(Communication.initiator_id, Communication.receiver_id)

people1 = aliased(People)
people2 = aliased(People)

sq = session.query(id1.label('id1'),
                   id2.label('id2'),
                   func.count(Communication.id).label('nb')).\
    filter(or_(Communication.initiator_id == people_id,
               Communication.receiver_id == people_id)).\
    order_by('nb').\
    group_by('id1', 'id2').\
    subquery()

q = session.query(sq.c.id1,
                  sq.c.id2,
                  func.coalesce(people1.orga_id, -1).label('orga_id1'),
                  func.coalesce(people2.orga_id, -1).label('orga_id2'),
                  sq.c.nb).\
    outerjoin(people1, people1.id == sq.c.id1).\
    outerjoin(people2, people2.id == sq.c.id2).\
    all()

【讨论】:

  • 非常感谢,这对我有帮助! :)
猜你喜欢
  • 2010-09-21
  • 2021-09-22
  • 2012-06-07
  • 2015-04-13
  • 1970-01-01
  • 2021-07-06
  • 1970-01-01
相关资源
最近更新 更多