繁体   English   中英

sqlalchemy连接并在多个表上排序

[英]sqlalchemy join and order by on multiple tables

我正在使用一个具有如下关系的数据库:

    class Source(Model):
       id = Identifier()

    class SourceA(Source):
       source_id = ForeignKey('source.id', nullable=False, primary_key=True)
       name = Text(nullable=False)

    class SourceB(Source):
       source_id = ForeignKey('source.id', nullable=False, primary_key=True)
       name = Text(nullable=False)

    class SourceC(Source, ServerOptions):
       source_id = ForeignKey('source.id', nullable=False, primary_key=True)
       name = Text(nullable=False)

我想要做的是联接所有表Source,SourceA,SourceB,SourceC,然后联接order_by名称。

对我来说听起来很轻松,但是我已经为此努力了一段时间,而且我的头开始受伤。 另外,我对SQL或sqlalchemy不太熟悉,因此浏览了很多文档,但无济于事。 也许我只是没有看到它。 似乎与我提供的较新版本(请参见下面的版本)密切相关。

我觉得这并不意味着什么。 这是我最近的尝试,直到order_by调用为止似乎都不错。

    Sources = [SourceA,  SourceB, SourceC]
    # list of join on Source
    joins = [session.query(Source).join(source) for source in Sources]
    # union the list of joins
    query = joins.pop(0).union_all(*joins)

据我所知,此时查询似乎是正确的,即query.all()有效。 因此,现在我尝试应用order_by ,在调用.all之前不会抛出错误。

尝试1:我只使用我想要的属性

    query.order_by('name').all()
    # throws sqlalchemy.exc.ProgrammingError: (ProgrammingError) column "name" does not exist

尝试2:我只是使用想要的已定义列属性

    query.order_by(SourceA.name).all()
    # throws sqlalchemy.exc.ProgrammingError: (ProgrammingError) missing FROM-clause entry for table "SourceA"

明显吗? 我想念什么? 谢谢!

版本:

SQLAlchemy的。 版本 ='0.8.1'

(PostgreSQL)9.1.3

编辑我正在处理一个想要查询对象句柄的框架。 我有一个简单的查询,看起来可以完成我想要的,但是我仍然需要将其包装在查询对象中。 不确定是否可行。 谷歌搜索...

select = """
    select s.*, a.name from Source d inner join SourceA a on s.id = a.Source_id
    union
    select s.*, b.name from Source d inner join SourceB b on s.id = b.Source_id
    union
    select s.*, c.name from Source d inner join SourceC c on s.id = c.Source_id
    ORDER BY "name";
"""
selectText = text(select)
result = session.execute(selectText)
# how to put result into a query. maybe Query(selectText)? googling...
result.fetchall():

假设coalesce功能足够好,下面的示例应为您指明方向。 一个选项会自动创建一个子列表,而另一个选项是显式的。

这不是您在编辑中指定的查询,但是可以排序(您的原始请求):

def test_explicit():
    # specify all children tables to be queried
    Sources = [SourceA, SourceB, SourceC]
    AllSources = with_polymorphic(Source, Sources)

    name_col = func.coalesce(*(_s.name for _s in Sources)).label("name")
    query = session.query(AllSources).order_by(name_col)
    for x in query:
        print(x)


def test_implicit():
    # get all children tables in the query
    from sqlalchemy.orm import class_mapper
    _map = class_mapper(Source)
    Sources = [_smap.class_
               for _smap in _map.self_and_descendants
               if _smap != _map  # @note: exclude base class, it has no `name`
               ]
    AllSources = with_polymorphic(Source, Sources)

    name_col = func.coalesce(*(_s.name for _s in Sources)).label("name")
    query = session.query(AllSources).order_by(name_col)
    for x in query:
        print(x)

您的第一次尝试听起来像是行不通的,因为Source(查询的根表)中没有名称。 另外,加入后将有多个名称列,因此您需要更加具体。 尝试

query.order_by('SourceA.name').all()

至于您的第二次尝试,什么是ServerA?

query.order_by(ServerA.name).all()

可能是拼写错误,但不确定是用于SO还是您的代码。 尝试:

query.order_by(SourceA.name).all()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM