繁体   English   中英

如何在sqlalchemy中合并两个查询-Raw和Orm?

[英]How can i combine two queries in sqlalchemy - raw and orm?

我有这些查询:

        funds_subq = text('''select distinct on (user_id) user_id,
last_value(amount) over(PARTITION BY user_id order BY id asc RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
from transactions order by user_id, ts_spawn desc''')

    g1 = aliased(Group)
    u1 = aliased(User)
    users = Session.query(User.id.label('user_id'),
                          User.name.label('user_name'),
                          User.funds.label('user_funds'),
                          Group.id.label('group_id'),
                          Group.parent_id.label('parent_id'),
                          u1.id.label('owner_id'),
                          u1.name.label('owner_name')). \
        select_from(User). \
        join(Group, Group.id == User.group_id). \
        outerjoin(g1, g1.id == Group.parent_id). \
        outerjoin(u1, u1.id == g1.owner_id)

那么,我如何才能将第一个加入第二个? 我尝试过这样的事情:

users = users.outerjoin(funds_subq, funds_subq.c.user_ud == User.id)

当然,它没有用,因为funds_subq没有c属性,也没有subquery()属性。 问题表明无法使用我的窗口查询版本。

如何实施查询?

我忘记了这个问题:)

有我的解决方案:

    from sqlalchemy.sql.expression import ColumnElement
from sqlalchemy.ext.compiler import compiles


class Extreme(ColumnElement):

    def __init__(self, request_column, partition_by, order_by, last=True):
        super(Extreme, self).__init__()
        self.request_column = request_column
        self.partition_by = partition_by
        self.order_by = order_by
        self.last = last

    # @property
    # def type(self):
    #     return self.func.type


def extreme_last(request_column, partition_by, order_by):
    """
    function returns last_value clause like this:
        last_value(transactions.remains) OVER (
        PARTITION BY transaction.user_id
        order BY transactions.id asc
        RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
    it returns last value of transaction.remains for every user, that means that we can get real balance of every user
    :param request_column: column, which last value we need
    :param partition_by: for what entity do we need last_value, e.g. user_id
    :param order_by: ordering for get last_value
    :return:
    """
    return Extreme(request_column, partition_by, order_by)


def extreme_first(request_column, partition_by, order_by):
    """
    as same as the `extreme_last` above, but returns first value
    :param request_column:
    :param partition_by:
    :param order_by:
    :return:
    """
    return Extreme(request_column, partition_by, order_by, last=False)


@compiles(Extreme)
def compile_keep(extreme, compiler, **kwargs):
    return "%s(%s) OVER (PARTITION BY %s order BY %s asc RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)" % (
        "last_value" if extreme.last else "first_value",
        compiler.process(extreme.request_column),
        compiler.process(extreme.partition_by),
        compiler.process(extreme.order_by)
    )

并且有一个使用示例。 查询返回每个用户最后一行的remains字段:

Session.query(distinct(Transaction.user_id).label('user_id'),
                         extreme_last(Transaction.remains,
                                      partition_by=Transaction.user_id,
                                      order_by=Transaction.id).label('remains'))

暂无
暂无

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

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