sqlalchemy在多个表上加入和排序

时间:2015-02-12 00:52:36

标签: python sql postgresql sqlalchemy

我正在使用具有以下关系的数据库:

    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,所以很多人都在浏览文档,但无济于事。也许我只是没有看到它。 This似乎很接近,虽然与我可用的版本有关(见下面的版本)。

我觉得 意味着什么。这是我最近的一次尝试,直到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():

2 个答案:

答案 0 :(得分:1)

假设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)

答案 1 :(得分:0)

您的第一次尝试听起来不起作用,因为Source中没有名称,这是查询的根表。此外,在您加入后会有多个名称列,因此您需要更具体。尝试

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

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

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

可能是一个错字,但不确定它是针对SO还是您的代码。尝试:

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